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


当前回答

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

其他回答

如果你不想写包装器,我想你可以这样做:

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

使用自定义路由组件,这在React Router v3中是可能的。

var Dashboard = require('./Dashboard');
var Comments = require('./Comments');
var routes = (
  <Route path="/" handler={Index}>
    <MyRoute myprop="value" path="comments" handler={Comments}/>
    <DefaultRoute handler={Dashboard}/>
  </Route>
);

对于<MyRoute>组件代码,它应该类似于:

import React from 'react';
import { Route } from 'react-router';
import { createRoutesFromReactChildren } from 'react-router/lib//RouteUtils';

const MyRoute = () => <div>&lt;MyRoute&gt; elements are for configuration only and should not be rendered</div>;

MyRoute.createRouteFromReactElement = (element, parentRoute) => {
    const { path, myprop } = element.props;
    // dynamically add crud route
    const myRoute = createRoutesFromReactChildren(
        <Route path={path} />,
        parentRoute
    )[0];
    // higher-order component to pass myprop as resource to components
    myRoute.component = ({ children }) => (
        <div>
            {React.Children.map(children, child => React.cloneElement(child, { myprop }))}
        </div>
    );
    return myRoute;
};

export default MyRoute;

有关自定义路由组件方法的更多详细信息,请查看我关于该主题的博客文章:http://marmelab.com/blog/2016/09/20/custom-react-router-component.html

你也可以结合es6和无状态函数来得到一个更清晰的结果:

import Dashboard from './Dashboard';
import Comments from './Comments';

let dashboardWrapper = () => <Dashboard {...props} />,
    commentsWrapper = () => <Comments {...props} />,
    index = () => <div>
        <header>Some header</header>
        <RouteHandler />
        {this.props.children}
    </div>;

routes = {
    component: index,
    path: '/',
    childRoutes: [
      {
        path: 'comments',
        component: dashboardWrapper
      }, {
        path: 'dashboard',
        component: commentsWrapper
      }
    ]
}

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

代码是这样的:

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

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

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