Home > Mobile >  React Component Recursion inside Route component
React Component Recursion inside Route component

Time:04-07

class AppRoutes extends Component {
  render () {
    return (
      <Suspense fallback={<Spinner/>}>
        <Switch>
          <Route exact path="/" component={ HomePage } />

            <Route exact path="/actions" 
            component={() => <Actions mode={0}/>}/>

          <Redirect to="/dashboard" />
        </Switch>
      </Suspense>
    );
  }
}

The constructor of the Actions component is called recursively.

I have also tried

            <Route exact path="/actions">
              <Suspense fallback={<Spinner/>}>
                <Actions mode={0}/>
              </Suspense>
            </Route>

But this just results in the same behaviour. I wish for the Actions component to only be called once rather than repetitively, and to allow props to be passed. How can this be accomplished?

CodePudding user response:

You are almost there except one.

Please use the following code for router "/actions".

class AppRoutes extends Component {
  render() {
    return (
      <Suspense fallback={<Spinner/>}>
        <Switch>
          <Route exact path="/" component={HomePage}/>
          <Route exact path="/actions"
                 render={routeProps => (
                   <Actions {...routeProps} mode={0} />
                 )}
          />
          <Redirect to="/dashboard"/>
        </Switch>
      </Suspense>
    );
  }
}

CodePudding user response:

When needing to pass additional props to routed components you'll need to the the render prop instead of the component prop for the following reason:

When you use component (instead of render or children, below) the router uses React.createElement to create a new React element from the given component. That means if you provide an inline function to the component prop, you would create a new component every render. This results in the existing component unmounting and the new component mounting instead of just updating the existing component.

What you are calling "The constructor of the Actions component is called recursively." is actually the Actions component being remounted repeatedly.

Use the render prop instead.

This allows for convenient inline rendering and wrapping without the undesired remounting explained above.

Instead of having a new React element created for you using the component prop, you can pass in a function to be called when the location matches. The render prop function has access to all the same route props (match, location and history) as the component render prop.

class AppRoutes extends Component {
  render () {
    return (
      <Suspense fallback={<Spinner/>}>
        <Switch>
          <Route
            path="/actions"
            render={(props) => <Actions mode={0} {...props} />}
          />
          <Route path="/" component={HomePage} />
          <Redirect to="/dashboard" />
        </Switch>
      </Suspense>
    );
  }
}

Note that the routes have also be ordered in decreasing order of path specificity so the more specific paths can be matched prior to the less specific paths. This eliminates the need to use the exact prop. This isn't an issue in react-router-dom@6 since it uses path rankings instead. Just an FYI when/if you update to the current version.

  • Related