【问题标题】:How does React separate old and new state after setState has been called?调用 setState 后 React 如何区分新旧状态?
【发布时间】:2020-09-09 16:04:28
【问题描述】:

在创建组件时 this.state 被定义。然后,在调用 setState 之后,React 以某种方式将旧状态和新状态拆分为两个对象。例如,使用钩子 shouldComponentUpdate 我们可以区分这两种状态,如下所示:

shouldComponentUpdate(nextProps, nextState) {
    return (this.state.foo != nextState.foo);
}

我从 github 下载了 React 源代码,并找到了调用这些函数的位置,但很快就很难跟踪发生了什么。我从来没有发现这种分裂(或者他们实现了这种行为)发生在哪里。我确实发现 React 曾经/可以使用浅比较来区分状态,所以我想知道他们是否只是简单地克隆状态对象,然后将更新的值合并到其中一个中,以便以后可以比较它们中的两个。它是否正确?在这种情况下,如何处理嵌套结构?还是他们使用某个版本的 get/set 和/或某个版本的 Proxy API 以某种方式捕获更改?

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    在使用 shouldComponentUpdate 的类概念的 react JS 中,如果我们不覆盖它,Component 将始终返回 true 并且 PureComponent 实现浅比较(浅比较通过检查两个值是否为在字符串、数字等原始类型的情况下相等,在对象的情况下,它只是检查 props 和 state 上的引用),如果任何 props 或 state 发生变化,则返回 true。

    如果我们覆盖 shouldComponentUpdate,我们将拥有先前的 props 和先前的状态。已经有存储在对象类组件中。对于下一个道具和下一个状态,我认为:

    • 下一个道具将传递给组件。所以,它是新的。
    • 下一个状态在函数setState 上处理。它是从以前的状态克隆的,并为此添加了新的更改。因此,前一个状态的引用和下一个状态的引用总是不同的。

    【讨论】:

      【解决方案2】:

      供将来参考:我设法在 React 源代码中找到了新状态偏离旧状态的位置。

      为此,我使用了 React Github 存储库的最新主分支(提交哈希 e7b255341b059b4e2a109847395d0d0ba2633999)。

      免责声明,这只是我的解释,我主要来自记忆。魔法发生在文件 packages/react-reconciler/src/ReactUpdateQueue.new.js 中,在函数 getStateFromUpdate 中。当调用 setState 时,会创建一个更新对象 (update.tag = UpdateState) 并将其添加到更新队列中(用于异步行为)。该标签用于此函数中的 switch 语句,用于特定的更新逻辑。在 UpdateState 案例的底部,我们看到 React 克隆 之前的状态并将其与“partialState”合并,这是传递给 setState 调用。此克隆使用:

      // Merge the partial state and the previous state.
      return Object.assign({}, prevState, partialState);
      

      从这个函数返回新的状态,之前的状态仍然存储在某个地方。它们现在可以用于以后的比较。附带说明一下,此处还处理了 ForceUpdate,它只是返回先前的状态(然后根据相同的逻辑成为新状态)。

      关于我的问题的第二部分,如何处理嵌套结构。鉴于这种新发现的知识,经过一番搜索,我找到了this question,它很好地回答了这个问题。

      【讨论】:

        猜你喜欢
        • 2020-07-04
        • 1970-01-01
        • 2018-09-23
        • 1970-01-01
        • 1970-01-01
        • 2019-01-28
        • 1970-01-01
        • 1970-01-01
        • 2017-11-18
        相关资源
        最近更新 更多