Reputation: 285
In react how can I configure a route to pass props. for example my route.tsx is:
export const routes = () => (
<Layout>
<Route exact path='/' component={ Home } />
<Route path='/counter' component={ Counter } />
<Route path='/fetchdata' component={ FetchData } />
</Layout>
);
How can I pass some data as props to my Counter
component when ever /counter is evoked
Upvotes: 8
Views: 7523
Reputation: 1074
As noted in other answers, this is handled by the render prop, which gives the example:
<Route path="/home" render={() => <div>Home</div>}/>
However, I (and many others) find this syntax pretty ugly. In the original issue on prop passing with Route, there's a well-liked wrapper which I wanted to surface, I've made some improvements and propose this terse and effective wrapper:
const PropsRoute = ({component, path, ...otherProps}) => (
<Route {...otherProps} path={path} render={routeProps =>
React.createElement(component, {...otherProps, ...routeProps})
} />
)
This can be used as might be expected:
<Router>
<main>
<PropsRoute exact path="/" component={Home} auth={this.state.auth} />
</main>
</router>
Note that doing this will pass the Route props down to the component. Any prop passed to Route that isn't 'component' or 'path' will be passed down to the component. In this formulation, any routeProps (passed by the react-router) will override custom props passed via this syntax.
This can then be quite easily expanded on to make the common login pattern:
const AuthedRoute = ({auth, ...props}) =>
!auth.valid()? <Redirect to="/login" />: <PropsRoute {...{...props, auth: auth}} />;
Edit: I've largely abandoned this approach as of 2019, in favour of something like this:
<Route {...{
path: "/path/to/component",
render: ({ location }) => <MyComponent {...{
location
}}/>
}}/>
This can appear a bit more gnarly, but it makes deeply nested render trees much clearer, and lets you use full Javascript in your JSX parameters.
Upvotes: 1
Reputation: 3411
You can use the render prop.
<Route
path='/counter'
render={(props) => (
<Counter {...props} count={5} />
)}
/>
Upvotes: 12
Reputation: 1118
To simplify things you could create a wrapper around <Route>
:
const RouteWrapper = ({ children, ...props }) => {
const childrenWithProps = props => React.Children.map(children, child => React.cloneElement(child, { ...props }))}
return <Route {...props} render={childrenWithProps} />
}
Usage:
<RouteWrapper
exact
path="/">
<Component myProp={38} />
</RouteWrapper>
Upvotes: 0
Reputation: 4983
This will do the work: Render
<Route
path='/dashboard'
render={(props) => <Dashboard {...props} isAuthed={true} />}
/>
Hope this helps!
Upvotes: 8