Problem
My React.js application, which uses React Router, has the following structure:
var Dashboard = require('./Dashboard');
var Comments = require('./Comments');
var Index = React.createClass({
render: function () {
return (
<div>
<header>Some header</header>
<RouteHandler />
</div>
);
}
});
var routes = (
<Route path="/" handler={Index}>
<Route path="comments" handler={Comments}/>
<DefaultRoute handler={Dashboard}/>
</Route>
);
ReactRouter.run(routes, function (Handler) {
React.render(<Handler/>, document.body);
});
I’d like to provide the Comments component certain characteristics.
(Normally, I’d use Comments myprop=”value” /> to do this.)
What’s the simplest and most effective method to achieve this with React Router?
Asked by Kosmetika
Solution #1
If you don’t want to write wrappers, you could do something like this:
class Index extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<h1>
Index - {this.props.route.foo}
</h1>
);
}
}
var routes = (
<Route path="/" foo="bar" component={Index}/>
);
Answered by Thomas E
Solution #2
It’s now allowed to give props directly to the Route component without needing a Wrapper, as of the latest release. Use render prop, for example.
Component:
class Greeting extends React.Component {
render() {
const {text, match: {params}} = this.props;
const {name} = params;
return (
<React.Fragment>
<h1>Greeting page</h1>
<p>
{text} {name}
</p>
</React.Fragment>
);
}
}
Usage:
<Route path="/greeting/:name" render={(props) => <Greeting text="Hello, " {...props} />} />
Codesandbox Example
Wrapping the Comments component and passing the wrapper as a route handler is my preferred method.
This is your example, with some modifications:
var Dashboard = require('./Dashboard');
var Comments = require('./Comments');
var CommentsWrapper = React.createClass({
render: function () {
return (
<Comments myprop="myvalue"/>
);
}
});
var Index = React.createClass({
render: function () {
return (
<div>
<header>Some header</header>
<RouteHandler/>
</div>
);
}
});
var routes = (
<Route path="/" handler={Index}>
<Route path="comments" handler={CommentsWrapper}/>
<DefaultRoute handler={Dashboard}/>
</Route>
);
ReactRouter.run(routes, function (Handler) {
React.render(<Handler/>, document.body);
});
Answered by ColCh
Solution #3
I’m copying from ciantic’s comments in the acceptable response:
<Route path="comments" component={() => (<Comments myProp="value" />)}/>
This, in my opinion, is the most graceful solution. It’s effective. It was beneficial to me.
Answered by Rajesh Naroth
Solution #4
This is Rajesh’s solution, updated for React Router 4 and without the inconvenient comments from Yuji.
This is how the code would look:
<Route path="comments" render={(props) => <Comments myProp="value" {...props}/>}/>
It’s worth noting that I’m using render instead of component. The reason for this is to prevent unwanted remounting. I also pass the props to that method, and I use the same props on the Comments component with the object spread operator (ES7 proposal).
Answered by Daniel Reina
Solution #5
This is just a follow-up to ColCh’s response. It’s really simple to abstract a component’s wrapping:
var React = require('react');
var wrapComponent = function(Component, props) {
return React.createClass({
render: function() {
return React.createElement(Component, props);
}
});
};
<Route path="comments" handler={wrapComponent(Comments, {myprop: value})}/>
I haven’t yet put this approach to the test, so any input is welcome.
It’s crucial to remember that any props sent over the Router (such as params) are rewritten / deleted when using this method.
Answered by sigmus
Post is based on https://stackoverflow.com/questions/27864720/react-router-pass-props-to-handler-component