I'm getting the match from my route using the hook like this
const match = useRouteMatch('/chat/:id');
and then I want to pass it down to child component. But when I'm passing it down I'm getting this error
Type 'match<{}> | null' is not assignable to type 'match<MatchParams>'.
In m child component I'm doing this
import { RouteComponentProps } from 'react-router';
interface MatchParams {
id: string;
}
interface ChildProps extends RouteComponentProps<MatchParams> {}
const Child = ({ match }: ChildProps ): React.ReactElement => {
return (
<>
<div>{match}</div>
</>
);
};
export default Child ;
Could someone help me figure out how to type all if this properly please?
Since the introduction of functional components, React has advanced a lot, for example, through the introduction of Hooks. Instead of normal class-based methods, Hooks allow the package to work well with functional components, and many packages are migrating in this direction. As a result, we see React Router Hooks.
Before the Hooks are introduced in React router, the component prop in the Route element is one of the methods used to render the components. But we now render them as a child element. And through one of the hooks, we can have access to the match object. This hook is called useRouteMatch. It is also available in the react-router-dom module.
The first thing you’d want to do when creating routing with the React router is to wrap the top-level app, in our case <TodoContainer> element in a router. Here, we introduced our first router component, BrowserRouter. So in the index.js file, import the component from the react-router-dom module.
1. useHistory: This is one of the most popular hooks provided by React Router. It lets you access the history instance used by React Router. Using the history instance you can redirect users to another page. The history instance created by React Router uses a Stack (called “History Stack”), that stores all the entries the user has visited.
We can use the internal mechanisms of React Router to match any route we want. If we take a look at this top level route, we can see that we want anything that matches /profile to pass on through to our App component. We could theoretically fix this by passing in /profile/:profileId and only rendering if we have an id match.
If you look at the return value of useRouteMatch
hook, it can be either of type
match<{}> | null
.
useRouteMatch
returns null, if the path that you have provided does not match. When you pass it down to the child component, you are sure that it is the correct match but TS is not sure as there was not a check to test for falsey values before passing it down.
The return is of type match
and not RouteComponentProps
.
match
is a generic which is empty object by default and this is where the params you expect will go in. To make TS aware you will have to pass this in.
This is how you would have to type it.
Parent.tsx
export interface MatchParams {
id: string;
}
const match = useRouteMatch<MatchParams>('/chat/:id');
return <Child match={match} />
Child.tsx
import { match } from 'react-router';
import { MatchParams } from './Parent';
interface ChildProps {
match: match<MatchParams> | null
}
const Child = ({ match }: ChildProps ): React.ReactElement => {
return (
<>
<div>{match}</div>
</>
);
};
export default Child ;
I believe the whole point of useRouteMatch
hook was to avoid passing around match
as props.
In case you want to get the match
or one of its inner properties (like params) you can use this hook directly in your child.
interface MatchParams {
id: string;
}
const Child = (): React.ReactElement => {
const match = useRouteMatch<MatchParams>();
return (
<>
<div>{match}</div>
<div>{match.params.id}</div>
</>
);
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With