【问题标题】:Redux componentDidUpdate use next propsRedux componentDidUpdate 使用 next 道具
【发布时间】:2019-01-18 14:25:52
【问题描述】:

componentDidUpdate 中导出数据的最佳做法是什么,将其推送到 redux 存储中,然后使用该数据进一步导出更多数据,然后再次将其推送到 redux 存储中?

鉴于 redux 是同步的,我希望能够在我完成调度后立即访问更新的 store,但我假设因为它仍在 componentDidUpdate 中,所以不会使用新的 store 数据更新 props通过mapStateToProps。即我试过 -

componentDidUpdate(){
    this.determineAndStoreA()
    this.doSomethingElse(this.props.A) // hoping this would be the updated A
}

this.props.A 仍然是旧值

我应该更像 -

componentDidUpdate(){
    const a = this.determineA()
    this.storeA(a);
    this.doSomethingElse(a) // using a local copy of A
}

经过进一步挖掘,我在https://github.com/reduxjs/react-redux/issues/291 中发现了一个类似的问题。 Dan 建议对 reducer 中的操作做出反应,但感觉我现在必须结合确定 A、从 A 确定 B、同时存储 A 和 B 的逻辑?

【问题讨论】:

  • determineA 中了解更多关于您在做什么会很有帮助。整个设置看起来像是一种代码味道。似乎导致此更新的操作仅由您的减速器部分处理,现在您的组件正在执行另一个工作步骤并分派给您的减速器。我会研究你是否可以让你的 reducer 一步完成,而不是将部分工作委托给组件。
  • 这是一个公平的评论,我在我的问题中添加了更多内容。我想你可能是对的,我会再通过一次,看看逻辑是否可以在一个 redux 操作/reducer 中组合和处理

标签: reactjs redux


【解决方案1】:

我想我明白你在挣扎什么。首先让我试着更全面地描述一下我认为你正在处理的场景。

您的商店中有ABC 派生自AB,所以如果A 发生变化,您需要重新派生C 并将其放入您的商店。然后,您可以拥有派生自 CD 的组件属性 E。操作x 更改A,现在您需要CE 的新值,并且很难一步完成而不会使reducer 过于复杂。

对于此类场景,我使用了三种主要方法,我会推荐哪一种取决于场景的具体情况。所有这些只是确定C 的方式/时间/地点的不同方法(并且可以扩展到进一步的推导,例如E)。

方法 1 在为处理动作的副作用而设计的中间件中计算C

这是与您已有的方法最相似的方法。它只是将其从组件中移出,因此您不会与商店之间的交互以及生命周期方法何时接收新信息作斗争。对于这种方法,我将使用 Redux Saga 并让它处理计算 C 以响应操作 x 并调度操作以使用 C 的新值更新存储。这样做很容易(如果你已经过了最初的 Redux Saga 学习曲线),因为 Redux Saga 在 store 已经更新后接收到 action。这种方法的主要缺点是您的商店将暂时处于不一致的状态,其中C 尚未反映对A 的更改。在某些情况下,这很重要,而在某些情况下则无关紧要。另一个潜在的缺点是,如果你还没有使用 Redux Saga,一开始可能会有点吓人,因为使用生成器函数和 yield 以及使用 Redux Saga 时的整个心态可能会让人觉得有点陌生(但我真的很喜欢在复杂的异步场景中使用 Redux Saga)。

方法 2 在动作创建器中计算 C

这通常涉及使用 thunk 作为对操作 x 的初始响应,然后 thunk 可以从存储中获取 B,计算 C 并使用包含两个部分的有效负载发送一个操作 - 一个已使用A 由减速器使用,C 由减速器使用。这种方法的主要缺点是如果C(即AB)的依赖关系可以通过多种方式改变,这可能会成为一种复杂的组织方式,但在某些情况下它可以正常工作.我大多放弃了这种方法,转而支持其他两种方法。

方法 3 不要将C 放在您的商店中。

如果C 完全来源于您商店中的其他东西,那么它实际上不需要在商店中。 C 只是您商店中其他信息的视图。您可以为此使用选择器。如果派生C 的成本很高,则使用记忆选择器。在还有从CD 派生的E 的更复杂的情况下,E 的选择器可以利用C 的选择器,同时从商店获取D。这是我通常喜欢的方法,除非有令人信服的理由让C 出现在商店中。这种方法可以让你的 reducer 保持简单和独立,同时让你的 store 保持一致的状态。

其他方法

还有其他方法可以做到这一点,但上面的 3 种方法是我自己实际使用过的方法。另一种方法是拥有一个利用其他减速器的减速器。在这种方法中,AB 的reducer 将由reducer 使用,然后计算C 并返回包含所有三个信息的状态。有一些包可以使以这种方式编写 reducer 变得更容易,但我没有使用它们,因为我对这种方法不是很感兴趣。对我来说,只是感觉放置这种复杂性的地方是错误的。

【讨论】:

    【解决方案2】:

    在 Redux 将值推送到 store 并触发组件的另一次更新时,您不会在同一周期中获得更新的 prop。

    您真的需要从 componentDidUpdate 触发这两个操作吗?

    您可以做的是创建一个新操作,该操作由您存储 A 值的操作触发。

    类似的东西

    store.dispatch(saveValueA()).then(() =>
      doSomeAction()
    );
    

    【讨论】:

      【解决方案3】:

      您的组件将在每次A 发生更改时重新渲染,并且componentDidUpdate 将被调用。

      然后您可以执行以下操作:

      componentDidUpdate(prevProps){
      
          const hasAChanged = this.props.A !=== prevprops.A;
      
          if (hasAChanged) {
              this.determineAndStoreA()
          } else {
              this.doSomethingElse(this.props.A)
          }
      }
      

      我不确定您要做什么,希望对您有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-08-26
        • 1970-01-01
        • 1970-01-01
        • 2019-06-30
        • 2021-11-06
        • 2021-07-09
        • 2017-01-17
        相关资源
        最近更新 更多