我有以下结构为我的React.js应用程序使用React路由器:

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

我想把一些属性传递给Comments组件。

(通常我会这样做,如<Comments myprop="value" />)

用React路由器最简单和正确的方法是什么?


当前回答

根据Rajesh Naroth回答使用带或不带路由器的组件。

class Index extends React.Component {

  constructor(props) {
    super(props);
  }
  render() {
    const foo = (this.props.route) ? this.props.route.foo : this.props.foo;
    return (
      <h1>
        Index - {foo}
      </h1>
    );
  }
}

var routes = (
  <Route path="/" foo="bar" component={Index}/>
);

或者你可以这样做:

export const Index = ({foo, route}) => {
  const content = (foo) ? foo : (route) ? route.foo : 'No content found!';
  return <h1>{content}</h1>
};

其他回答

更新

自新版本以来,可以直接通过Route组件传递道具,而不使用Wrapper。例如,通过使用渲染道具。

组件:

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

用法:

<Route path="/greeting/:name" render={(props) => <Greeting text="Hello, " {...props} />} />

Codesandbox例子


旧版本

我更喜欢的方法是包装Comments组件,并将包装器作为路由处理程序传递。

这是应用更改后的示例:

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

你也可以使用RouteHandler mixin来避免包装器组件,更容易地将父类的状态作为道具传递下去:

var Dashboard = require('./Dashboard');
var Comments = require('./Comments');
var RouteHandler = require('react-router/modules/mixins/RouteHandler');

var Index = React.createClass({
      mixins: [RouteHandler],
      render: function () {
        var handler = this.getRouteHandler({ myProp: 'value'});
        return (
            <div>
                <header>Some header</header>
                {handler}
           </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);
});

React路由器的问题是它会渲染你的组件,因此会阻止你传入道具。另一方面,导航路由器允许你渲染你自己的组件。这意味着您不必像下面的代码和附带的JsFiddle显示那样跳过任何障碍来传递道具。

var Comments = ({myProp}) => <div>{myProp}</div>;

var stateNavigator = new Navigation.StateNavigator([
  {key:'comments', route:''}
]);

stateNavigator.states.comments.navigated = function(data) {
  ReactDOM.render(
    <Comments myProp="value" />,
    document.getElementById('content')
  );
}

stateNavigator.start();

对于react-router 2.5.2,解决方案非常简单:

    //someConponent
...
render:function(){
  return (
    <h1>This is the parent component who pass the prop to this.props.children</h1>
    {this.props.children && React.cloneElement(this.props.children,{myProp:'value'})}
  )
}
...

你可以像这样通过<RouterHandler/>传入props:

var Dashboard = require('./Dashboard');
var Comments = require('./Comments');

var Index = React.createClass({
  render: function () {
    var props = this.props; // or possibly this.state
    return (
        <div>
            <header>Some header</header>
            <RouteHandler {...props} />
        </div>
    );
  }
});

这样做的缺点是你不加区别地传递道具。因此,Comments可能最终接收到的道具实际上是针对不同组件的,这取决于您的路由配置。这不是什么大问题,因为props是不可变的,但如果两个不同的组件都期望一个名为foo的道具,但值不同,这就会出现问题。