I have a component ViewRestaurant.js
that is part of a react-router
(using 5.2). I'm trying to access a dynamic URL parameter ("/view-restaurant/:id"
, the id
)
Snippet from App.js
(the main data loader):
return (
<Router>
<div>
<Route
exact
path="/"
component={() => (
<Main
restaurants={this.state.restaurants}
account={this.state.account}
/>
)}
/>
<Route
path="/view-restaurant/:id"
component={() => (
<ViewRestaurant
restaurants={this.state.restaurants}
account={this.state.account}
/>
)}
/>
</div>
</Router>
);
This is how I'm trying to put the Link
, snippet from Main.js
which displays a list of restaurants:
<Link
to={{
pathname: '/view-restaurant/' + key,
state: { id: key }
}}
>
View
</Link>
But when I'm trying to access what I've passed, meaning the id
, which is the same as key
in Main.js
, it doesn't work.
Snippet from ViewRestaurant.js
:
render() {
const restaurants = this.props.restaurants
console.log(restaurants[0].name) // this works.
console.log(this.state.id) // this throws the error.
// return removed for readability
}
The error: TypeError: this.state is null
According to the documentation, we should be able to create a state and pass it via link. I'm 100% sure I'm misinterpreting the documentation, but I just don't know how to solve this error.
I figured it out eventually. Just don't use classic components with the render function that returns stuff.
The way in React Router v5 (v5.2 in my case) is to pass props via functions and get parameters via a special function.
For this specific issue I had, only had to use useParams()
from the new React-Router documentation and completely refactor my code to use functions and hooks instead.
I highly recommend to ditch clasic classes that use the render()
function and move to the improved way of coding using the new React-Router.
Youtube video that teaches you how to pass props
Documentation on useParams()
How I solved it:
function ViewRestaurant({ restaurants }) {
const { id } = useParams();
}
and in Main.js (note that the key is obtained via a simple js map)
<Link to={{ pathname: '/view-restaurant/' + key}}>View</Link>
and finally, App.js
<Route path="/view-restaurant/:id">
<ViewRestaurant
restaurants={this.state.restaurants} />
</Route>