react-router - 将props传递给处理程序组件

IT技术 javascript properties reactjs react-router
2021-02-04 23:29:18

我的 React.js 应用程序使用React Router具有以下结构

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 Router 这样做的最简单和正确的方法是什么?

6个回答

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

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}/>
);
不!有关真正的解决方案,请参阅 Rajesh Naroth 的答案:)
2021-03-18 23:29:18
万分谢意!如果有人想知道, foo 属性将在您的组件中可用: this.props.route.foo
2021-03-19 23:29:18
这是我一直在寻找的简单答案。其他技术有效,但需要 10 倍的代码量。适用于 v1.0.x。我能看到的唯一缺点是,如果您打算在有和没有路由器容器的情况下使用相同的组件。但对我来说,我所有的顶级组件都与路由一对一地映射。
2021-03-20 23:29:18
这是一个正确的答案。在 react-router 1.0 中,您可以route在组件中获取普通对象。这是github问题的答案:github.com/rackt/react-router/issues/615#issuecomment-100432086
2021-04-10 23:29:18
可以将此设置为正确答案以避免混淆吗?
2021-04-10 23:29:18

更新

从新版本开始,可以直接通过Route组件传递 props ,而无需使用 Wrapper。例如,通过使用renderprop

零件:

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

代码沙盒示例


旧版

我的首选方法是包装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);
});
我永远不会同意创建额外的组件只是为了传递属性是“首选方式”。它冗长、复杂、容易出错,而且在所有可以想象的方面都是明显错误的。这可能是反应路由器允许的唯一方式,但称其为“首选”是一种延伸。被谁偏爱?
2021-03-23 23:29:18
我遇到了同样的问题,但是这个解决方案不会很快变得冗长吗?
2021-04-03 23:29:18
同意 captDaylight,它变得冗长。希望有更好的方法来处理这个问题!
2021-04-04 23:29:18
@mattiashallstrom IMO,1.0 中更好的方法是简单地将属性添加到路由中。参见 Thomas E 的回答。
2021-04-06 23:29:18
你也可以在那里添加一个无状态组件语法(只是 lambda),它很短 <Route path="comments" component={() => (<Comments myProp="value" />)}/>
2021-04-07 23:29:18

ciantic在接受的回复中复制评论

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

这是我认为最优雅的解决方案。有用。帮助过我。

从 React-Router 4 开始,如果您提供内联函数,您将获得很多不需要的重新安装。对于内联渲染,请使用 render 道具。链接到文档
2021-03-18 23:29:18
@JacobThomason 我们不会重新渲染 react 路由器配置,因此它不太可能是性能损失。
2021-03-27 23:29:18
@yuji 为了不让它太乱,可以这样做:component={(props) => (<Comments {...props} myProp="value" />)}维护注入的道具
2021-03-27 23:29:18
这与上面的包装器答案基本相同,但不那么冗长。但是,这种语法很糟糕。尝试扔一个_ref
2021-04-04 23:29:18
它就像一个匿名包装器,所以所有注入的道具(例如位置)都被遗漏了。一个人必须手动传递道具,component={(props) => (<Comments myProp="value" location={ props.location } />)}但它又变得一团糟
2021-04-09 23:29:18

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

代码如下:

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

请注意,我使用render代替component. 原因是为了避免不需要的重新安装我还将 传递props给该方法,并且我在 Comments 组件上使用了相同的 props 和对象扩展运算符(ES7 提议)。

解决不需要的安装也非常棒!+1
2021-03-20 23:29:18

只是对 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})}/>

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

重要的是要注意,使用此方法,通过路由器发送的任何props(例如参数)都会被覆盖/删除。

您可能还想通过孩子。| var wrapComponent = function(Component, props) { return React.createClass({ render: function() { return React.createElement(Component, props, this.props.children); } }); };
2021-03-17 23:29:18
如果您还需要来自路由器的查询和参数,那么这样的事情将起作用:(return React.createElement(Component, _.assign({}, this.props, props));这个使用 _.assign 来组合组合对象......当然还有其他方法可用)。
2021-03-18 23:29:18
Bob,你熟悉闭包吗?stackoverflow.com/questions/111102/...
2021-03-19 23:29:18
对于那些不熟悉它们的人来说,这是一个高阶组件facebook.github.io/react/docs/higher-order-components.html
2021-04-08 23:29:18
注意这是现在用于旧版本的 React Router。当前的 v4 有rendercomponent和 的children方法Route请注意,正如@dgrcode 回答指出的那样,您应该使用render而不是component
2021-04-09 23:29:18