If match
prop is undefined this could be from a few things.
react-router-dom
v5
If using RRDv5 if the match
prop is undefined this means that BookScreen
isn't receiving the route props that are injected when a component is rendered on the Route
component's component
prop, or the render
or children
prop functions. Note that using children
the route will match and render regardless, see route render methods for details.
Ensure that one of the following is implemented to access the match
object:
Render BookScreen
on the component
prop of a Route
<Route path="...." component={BookScreen} />
Render BookScreen
on the render
or children
prop function of a Route
and pass the route props through
<Route path="...." render={props => <BookScreen {...props} />} />
or
<Route path="...." children={props => <BookScreen {...props} />} />
Decorate BookScreen
with the withRouter
Higher Order Component to have the route props injected
import { withRouter } from 'react-router-dom';
function BookScreen = ({ match }) {
const book = books.find((b) => b._id === match.params.id)
return (
<div>
{book}
</div>
);
};
export default withRouter(BookScreen);
Since BookScreen
is a React function component, import and use the useParams
hook to access the route match params
import { useParams } from 'react-router-dom';
...
function BookScreen() {
const { id } = useParams();
const book = books.find((b) => b._id === id)
return (
<div>
{book}
</div>
);
}
react-router-dom
v6
If using RRDv6 then there is no match
prop. Gone are the route props. Here only the useParams
and other hooks exist, so use them.
import { useParams } from 'react-router-dom';
...
function BookScreen() {
const { id } = useParams();
const book = books.find((b) => b._id === id)
return (
<div>
{book}
</div>
);
}
If you've other class components and you're using RRDv6 and you don't want to convert them to function components, then you'll need to create a custom withRouter
component. See my answer here with details.