Search code examples
javascriptreactjsreact-routerreact-router-dom

React-router 5.2 failure to get parameter from URL


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.


Solution

  • 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>