react-router – pass props to handler component

react-router – pass props to handler component

I have the following structure for my React.js application using React Router:
var Dashboard = require(‘./Dashboard’);
var Comments = require(‘./Comments’);

var Index = React.createClass({
render: function () {
return (

Some header

);
}
});

var routes = (




);

ReactRouter.run(routes, function (Handler) {
React.render(, document.body);
});

I want to pass some properties into the Comments component.
(normally I’d do this like )
What’s the easiest and right way to do so with React Router?

Solutions/Answers:

Solution 1:

UPDATE

Since new release, it’s possible to pass props directly via the Route component, without using a Wrapper. For example, by using render prop.

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


OLD VERSION

My preferred way is wrap the Comments component and pass the wrapper as a route handler.

This is your example with changes applied:

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);
});

Solution 2:

If you’d rather not write wrappers, I guess you could do 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}/>
);

Solution 3:

Copying from the comments by ciantic in the accepted response:

<Route path="comments" component={() => (<Comments myProp="value" />)}/>

This is the most graceful solution in my opinion. It works. Helped me.

Solution 4:

This is the solution from Rajesh, without the inconvenient commented by yuji, and updated for React Router 4.

The code would be like this:

<Route path="comments" render={(props) => <Comments myProp="value" {...props}/>}/>

Note that I use render instead of component. The reason is to avoid undesired 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).

Solution 5:

Just a follow-up to ColCh’s answer. It is quite easy to abstract the wrapping of a component:

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 tested this solution yet so any feedback is important.

It’s important to note that with this method, any props sent via the Router (such as params) get overwritten / removed.

Solution 6:

You can pass props by passing them to <RouteHandler> (in v0.13.x) or the Route component itself in v1.0;

// v0.13.x
<RouteHandler/>
<RouteHandler someExtraProp={something}/>

// v1.0
{this.props.children}
{React.cloneElement(this.props.children, {someExtraProp: something })}

(from the upgrade guide at https://github.com/rackt/react-router/releases/tag/v1.0.0)

All child handlers will receive the same set of props – this may be useful or not depending on the circumstance.