Coder Perfect

pass props to handler component with react-router

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