Cannot read property ‘params’ of undefined (React Router 4)

ghz 6months ago ⋅ 60 views

I have a route set up to render a component:

<Route exact path="/page/:id" location={this.props.location} key={this.props.location.key} render={({ location }) => (
    <PageStart key={this.props.location.key} />
)} />

Then inside that component (PageStart) I have:

this.props.match.params.id

But it throws an error:

Cannot read property 'params' of undefined

Passing props when simply calling component={} seems to work fine but not in a render function. Why?

Answers

The issue you're encountering stems from how the render prop in your Route component is structured. When using render={({ location }) => ...}, the props like match, history, and location are not automatically passed down to the component rendered by the render function. Instead, you need to explicitly pass them if you want the component to receive them as props.

Here's how you can modify your Route setup to ensure that PageStart receives the necessary props (match, location, history):

<Route
  exact
  path="/page/:id"
  render={(routeProps) => (
    <PageStart {...routeProps} key={routeProps.location.key} />
  )}
/>

Explanation:

  1. routeProps: When you use the render prop in a Route, React Router passes several props to the function:

    • match: Information about how the URL matches the route path.
    • location: The current location object.
    • history: A history object that allows programmatic navigation.
  2. Passing props: In the render function, routeProps (or any name you choose) is an object containing these props. By spreading routeProps ({...routeProps}), you pass all these props explicitly to the PageStart component.

  3. Accessing params: Inside PageStart, you can access params using this.props.match.params.id because match will now be defined and contain the matched parameters from the URL.

Example Usage:

Assuming your PageStart component looks like this:

import React from 'react';

class PageStart extends React.Component {
  render() {
    const { match } = this.props;
    const id = match.params.id; // Access the id parameter from the URL

    return (
      <div>
        <h1>PageStart Component</h1>
        <p>Parameter ID: {id}</p>
      </div>
    );
  }
}

export default PageStart;

With the corrected Route setup as shown above, PageStart will receive match, location, and history props correctly, and you can access this.props.match.params.id without encountering the "Cannot read property 'params' of undefined" error.

Conclusion:

Always ensure that when using the render prop in React Router, you pass down the necessary props explicitly to the component you render. This approach gives you more control over which props are passed and helps avoid confusion or errors related to undefined props.