【问题标题】:React router remounts children while changing routes (without reconciliation)React 路由器在更改路由时重新安装子节点(没有协调)
【发布时间】:2018-06-02 18:21:05
【问题描述】:

我遇到的情况是,很少有路由包含相同的组件,我想保留它的状态,但这种行为几乎是不可能的。

实时示例(查看经过的秒数): https://csb-43lp1km647-nkiinaibit.now.sh

代码沙盒: https://codesandbox.io/s/43lp1km647

当然,我可以在更改路线时保存和恢复计时器状态,但我的应用程序有一个无限的 CSS 过渡作为背景(不是在每条路线上)。

我正在尝试添加密钥,甚至是门户,但它仍然会重新安装所有内容。

有没有办法强制执行典型的 React 的 reconciliation(仅重新安装必须重新安装的元素)?

更新: 刚刚发现<Switch /> 将渲染所有内容,直到找到匹配的元素,这可能是某个<Route /> 或除<Fragment /> 之外的任何元素。

代码:

<Router history={history}>
  <Switch>
    <Route path="/third" component={RouteWithoutTimer} />
    <React.Fragment>
      <Timer />
      <Route exact path="/" component={FirstRoute} />
      <Route path="/second" component={SecondRoute} />
    </React.Fragment>
  </Switch>
</Router>

或使用通配符路由:

<Router history={history}>
  <Switch>
    <Route path="/third" component={RouteWithoutTimer} />
    <React.Fragment>
      <Timer />
      <Switch>
        <Route exact path="/" component={FirstRoute} />
        <Route component={NotFoundRoute} />
      </Switch>
    </React.Fragment>
  </Switch>
</Router>

这不是我正在寻找的解决方案,但它工作正常。

【问题讨论】:

  • 当我最后一次遇到这个问题时,我只是重组了组件树,以便只有一个组件被卸载(在你的情况下,定时器)。你有可能这样做吗?您可以做的另一件事是将计时器的状态提升到应用程序,然后将其作为道具传递。
  • @gorhawk 感谢您的回复。它是带有 CSS 过渡(背景)的元素,因此无法提升状态。现在我在应用程序的状态中有一个变量,它指示是否应该渲染这个元素,并且在应用程序的上下文中有两个函数,它改变了这个变量的值。每条路线都调用足够的函数来渲染/不渲染背景。想知道是否有更简单、更优雅的解决方案。
  • 我想建议使用react-redux,但这似乎有点矫枉过正
  • @gorhawk 看看更新。
  • 对不起,我以为你熟悉Switch,我指的是这样的东西。如果你认为这更优雅,那就去吧:D

标签: javascript reactjs react-router


【解决方案1】:

您正在每条路由中安装 Timer 的新实例。
如果你想跨路由共享一个组件,你应该把它提升到路由的父组件:

<React.Fragment>
  <Timer />
  <Switch>
    <Route exact path="/" component={FirstRoute} />
    <Route path="/second" component={SecondRoute} />
  </Switch>
</React.Fragment>

【讨论】:

  • 在这种情况下它可以工作,但如果我想在没有Timer 的情况下留下一条路线,那么我必须在每条路线中实现额外的逻辑。
  • 什么额外的逻辑?你能详细说明一下吗?
  • 感谢您的回复。将&lt;Fragment /&gt; 移动到&lt;Switch /&gt; 解决了我的问题。看更新。
【解决方案2】:

这就是状态管理库出现的地方。

在 React 中,状态是每个组件的,并且具有其拥有的组件的生命周期,因此当路由器销毁/重新安装组件时,您会丢失所有数据。我建议您尽快将您的状态迁移到像redux 这样的状态管理库。否则,如果这是一个中型应用程序,您的代码可能会很混乱。

【讨论】:

    猜你喜欢
    • 2018-08-06
    • 2018-06-09
    • 2021-09-28
    • 2020-08-05
    • 2017-06-25
    • 2019-06-04
    • 2019-11-27
    • 1970-01-01
    • 2020-04-25
    相关资源
    最近更新 更多