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
.
Top comments (0)