我有以下结构为我的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路由器最简单和正确的方法是什么?


当前回答

你可以像这样通过<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的道具,但值不同,这就会出现问题。

其他回答

你可以通过将它们传递给<RouteHandler>(在v0.13.x中)或v1.0中的Route组件本身来传递道具;

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

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

(来自https://github.com/rackt/react-router/releases/tag/v1.0.0的升级指南)

所有子处理程序都将收到相同的一组道具——这可能有用,也可能没用,取决于具体情况。

React-router v4 alpha

现在有了一种新的方法,尽管和之前的方法很相似。

import { Match, Link, Miss } from 'react-router';
import Homepage from './containers/Homepage';

const route = {
    exactly: true,
    pattern: '/',
    title: `${siteTitle} - homepage`,
    component: Homepage
  }

<Match { ...route } render={(props) => <route.component {...props} />} />

附注:这只适用于alpha版本,并且在v4 alpha发布后被删除。在v4 latest中,同样是带有路径和精确props的。

React-lego是一个示例应用程序,它在react-router-4分支的routes.js中包含了这样做的代码

只是ColCh回答的一个后续问题。抽象一个组件的包装是很容易的:

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

我还没有测试这个解决方案,所以任何反馈都很重要。

需要注意的是,使用这种方法,任何通过Router发送的道具(比如params)都会被覆盖/删除。

React路由器v5.1 (React >= 16.8)这样做的方式:

<Route path="/comments">
    <Comments myprop="value" />
</Route>

现在,如果你想访问组件中的Route Props,你可以参考这个解决方案。对于函数组件,还有另一个钩子useParams()在那篇文章中没有提到。

更多参考:React Router v5.1

这是来自Rajesh的解决方案,没有yuji的不便评论,并为React Router 4更新。

代码是这样的:

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

注意,我使用渲染而不是组件。原因是为了避免不必要的重新挂载。我还将道具传递给该方法,并在Comments组件上使用对象展开操作符(ES7建议)。