DEV Community

Truong Hoang Dung
Truong Hoang Dung

Posted on

10 3

A React Hook for universal routing

I'm using @reach/router and love its simplicity.
But i love to use React Hook to get the page params and query string, so i make a simple hook for it.

Firstly, we need a pageContext for page component.

pageContext.ts:

import React, { createContext } from 'react';

const pageContext = createContext({} as any);

export const withPageContext = (Component: any) => (props: any) => {
  return (
    <pageContext.Provider value={{...props}}>
      <Component {...props} />
    </pageContext.Provider>
  );
};

export default pageContext;

This also includes a HOC to inject props into pageComponent to be consumed with useContext hook later.

Second, we need to wrap this pageContext.Provider to all Route component:
Route.tsx:

import React, { 
  FunctionComponent 
} from 'react';
import { 
  RouteComponentProps 
} from '@reach/router';
import {
  LoadableComponent
} from '@loadable/component';
import { withPageContext } from './pageContext';

type Props = { component: FunctionComponent | LoadableComponent<{}> } & RouteComponentProps;

const Route: FunctionComponent<Props> = ({ component, ...rest }) => {
  const Component = withPageContext(component);
  return (
    <Component {...rest} />
  );
};

export default Route;

And lastly, the thing we need, a useRouter hook:
useRouter.ts

import pageContext from './pageContext';
import { useContext } from 'react';
import { parse, parseUrl } from 'query-string';
const isServer = typeof(window) === 'undefined';

const useRouter = () => {
  const { location, ...rest } = useContext(pageContext);
  const queryParams = isServer ?  
    parseUrl(location.pathname).query : 
    parse(location.search);

  const query = {
    ...queryParams,
    ...rest,
  };

  return { query };
};

export default useRouter;

Here, i mapped all props and query string into a query property returned by useRouter and we've done !

Usage:

Firstly, declare your routes with our new Route component:

App.tsx:

import React from 'react';
import Route from './Route';
import { 
  Router 
} from '@reach/router';
import loadable from '@loadable/component';

const User = loadable(() => import('components/User'));

const App = () => {
  return (
    <Router>      
      <Route component={User} path="/users/:userId" />
    </Router>
  );
};

export default App;

Secondly, use useRouter in our User component:

User.tsx:

import React from 'react';

const User = () => {
  const { query } = useRouter();
  const { userId } = query;
  return <div>You requested {userId}</div>;
};

Inspiration:

This is inspired by react-router and nextjs.

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

Top comments (0)

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

Rather than just generating snippets, our agents understand your entire project context, can make decisions, use tools, and carry out tasks autonomously.

Read full post

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay