16

我在给定的路线上有一个组件,比如说app.com/cars/1

我有一个侧边栏,其中包含指向不同汽车的链接,例如/cars/2/cars/3

我遇到的问题是当您更改链接时,例如 go from cars/1to cars/2,组件没有卸载,我被componentWillReceiveProps解雇了。如果我使用不同的组件转到另一个页面,例如/trucks,该组件已卸载并且一切正常。

路由更改时如何卸载组件?我有各种状态和通量的东西,我想为下一辆车清除。或者如果不卸载,人们是否有处理这类问题的典型方式?我无法想象这不是很常见。

(注意我使用的是反应路由器)

4

3 回答 3

16

我认为处理这个问题的正常方法只是取消注册和重新注册你的听众,重置你的状态,等等componentWillReceiveProps。围绕这种行为创建抽象是正常的:

componentWillMount: function() {
  this.setupStuff(this.props);
}

componentWillUnmount: function() {
  this.tearDownStuff();
}

componentWillReceiveProps: function(nextProps) {
  this.tearDownStuff();
  this.setupStuff(nextProps);
}

setupStuff: function(props) {
  this.setState(this.getDataFromStore(props.store));
  props.store.listen(this.handler); // or whatever
}

tearDownStuff: function(props) {
  props.store.unlisten(this.handler); // or whatever
}

但是,如果您真的想重新安装组件,可以使用几个选项。

如果您不希望任何组件在路由更改时保持挂载,您可以利用路由器createElement选项为组件添加唯一键:

function createElement(Component, props) {
  var key = ...; // some key that changes across route changes
  return <Component key={key} {...props} />;
}

// ...

<Router createElement={createElement}>
  ...

但是,我不建议这样做。它不仅使您的应用程序变慢,因为每个路由组件每次都重新安装,而且它还完全禁用了相同路由处理程序具有不同道具的后续渲染之间的动画之类的东西。

如果您只想始终重新渲染某个路线,则可以通过以下方式在父级中为其提供一个键React.cloneElement

render: function() {
  var key = ...; // some key that changes across route changes
  return React.cloneElement(
    React.Children.only(this.props.children),
    {key: key}
  );
}
于 2015-10-06T03:59:49.133 回答
3

我最终只是在做:

const createElement = (Component, props) =>
  <Component key={props.params.id} {...props}/>;

ReactDOM.render(
  <Router history={browserHistory} createElement={createElement}>
    <Route path="courses/:id" component={Page_courses_id}/>
  </Router>
);

并且忽略潜在的性能问题(如果它们曾经发生),在我看来维护成本(重置所有组件的状态:动态段,在 componentWillReceiveProps 中重新获取数据等)是不值得的。

于 2017-10-12T06:42:57.660 回答
1

我选择了带有更改密钥的 Michelle Tilley 选项,但我没有为路由器中的整个组件设置密钥,而只是为我需要通过重新启动挂钩来更新的那个组件设置密钥。

这很好用。

const UniqComponent = () => {
  const uniqId = 123; // may be carId
  return <div key={uniqId} />
}

ReactDOM.render(
  <Router history={browserHistory}>
    <Route path="cars/:id" component={UniqComponent}/>
  </Router>
);

于 2021-06-11T16:58:56.313 回答