React 的状态更新过程中React Element,current Fiber,workInProgress Fiber是如何工作的

79 阅读3分钟

在 React 的状态更新过程中,React Elementcurrent FiberworkInProgress Fiber 这三者确实按照上述方式协同工作。为了确保你理解得更清楚,我可以再详细解释一下这些概念,并进一步梳理它们的工作关系。

状态更新的详细流程:

1. 触发状态更新

  • 用户操作或组件内的状态变化会触发 React 的更新机制。
  • React 会根据 setStateprops 的变化,生成一个新的 React Element,这个新的 React Element 描述了组件的新 UI 状态。

2. 比较当前状态和新的 React Element

  • React 会在 Render 阶段 创建一个新的 workInProgress Fiber。这个新 Fiber 树会基于新的 React Element 生成,并与当前的 current Fiber 进行对比。

    • 如果类型和 key 相同,React 会复用节点,更新其 props
    • 如果节点类型或 key 不同,React 会标记为需要删除旧节点并插入新节点。

3. 创建和更新 workInProgress Fiber

  • beginWork 阶段,React 会遍历 workInProgress Fiber 树,并根据 React Element 的变化和 current Fiber 的状态,决定哪些节点需要更新,哪些节点需要插入或删除。
  • workInProgress Fiber 节点不仅仅包含了节点类型、propskey 等信息,还包括了副作用标记(effectTag)。
  • 副作用标记(PLACEMENTUPDATEDELETION 等)会在 effectList 中收集,并在 Commit 阶段 执行。

4. 收集副作用(effect list)

  • Render 阶段 中,React 会收集副作用并记录在 workInProgress FibereffectTageffectList 中。

    • 如果 React Elementcurrent Fiber 之间存在差异(比如 props 变化),则相应的节点会被标记为 UPDATE
    • 如果新节点需要插入或删除,会分别标记为 PLACEMENTDELETION
    • 这些副作用会被存储在 effectList 中,形成链表结构,等待在 Commit 阶段执行。

5. 完成 workInProgress Fiber 构建

  • workInProgress Fiber 树构建完成后,它会作为新的 current Fiber,用于下一轮渲染。
  • Render 阶段 完成后,React 交换 current FiberworkInProgress Fiber,并将 effectList 中的副作用提交到页面中。

6. Commit 阶段

  • Commit 阶段,React 会根据 effectList 中记录的副作用进行实际的 DOM 更新操作:

    • 插入、更新或删除对应的节点。
    • 执行生命周期方法(如 componentDidMountcomponentDidUpdate)。
    • 执行 useEffect 或其他副作用函数。

总结:三者的协作流程

  • React Element:每次状态更新都会生成一个新的 React Element,它描述了组件的新 UI。它是 UI 的静态描述对象,纯粹的描述信息。
  • current Fiber:表示当前已渲染到屏幕上的状态,它记录了真实 DOM 的当前状态和属性。每个 Fiber 节点对应一个已渲染的 UI 元素。
  • workInProgress Fiber:表示正在构建的新的 Fiber 树,基于新的 React Element 生成。在 Render 阶段workInProgress Fiber 会与 current Fiber 对比并更新需要改变的部分。它会收集副作用,并在 Commit 阶段 执行。

三者的关系和协同工作:

  1. React Element 提供了 UI 状态 的描述。
  2. current Fiber 代表了 已渲染的 UI 状态
  3. workInProgress Fiber正在构建的更新状态,会根据新的 React Elementcurrent Fiber 的差异,决定哪些部分需要更新,并且记录副作用。

React 在更新过程的 Render 阶段 使用 workInProgress Fiber 来对比旧的 current Fiber,并生成新的 workInProgress Fiber 树,同时收集副作用。最后,effectList 中的副作用会在 Commit 阶段 被执行,更新实际的 DOM 或组件状态。


如果你对这个过程还有疑问,可以进一步讨论。