如何在路由更改时卸载组件



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

我有一个侧边栏链接到不同的汽车,如/cars/2, /cars/3

我遇到的问题是,当你改变链接,说从cars/1cars/2,组件不卸载,我得到componentWillReceiveProps解雇。如果我转到另一个具有不同组件的页面,例如/trucks,则该组件被卸载,一切正常。

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

(注意我使用的是react-router)

我认为处理这个问题的正常方法是在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}
  );
}

最后我做了:

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

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

我选择了带有change key的Michelle Tilley选项,但是我没有为路由器中的整个组件设置key,而只是为需要通过重启钩子进行更新的组件设置key。

const UniqComponent = () => {
  const uniqId = 123; // may be carId
  return <div key={uniqId} />
}
ReactDOM.render(
  <Router history={browserHistory}>
    <Route path="cars/:id" component={UniqComponent}/>
  </Router>
);

相关内容

  • 没有找到相关文章

最新更新