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 ofrender
orchildren
, below) the router usesReact.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.