标准答案
- 渲染阶段会调用组件函数,计算 React element,执行协调和 diff,得到需要提交的变更。
- 在并发能力下,渲染阶段可能被中断、重启或丢弃,所以渲染逻辑必须纯粹。
- 提交阶段会真正修改 DOM、更新 ref,并执行 useLayoutEffect 的清理和创建。
- 浏览器绘制后,React 会执行 useEffect 这类被动副作用。
- 理解这两个阶段有助于区分为什么不能在 render 里写副作用,以及 useLayoutEffect 和 useEffect 的时机差异。
题目解析
这道题是很多高级 React 问题的基础。渲染阶段是计算,提交阶段是落地。
render phase 可中断,所以不能做网络请求、订阅、写缓存、改全局变量等副作用。
commit phase 不可中断,因为一旦开始修改 DOM,就需要保持 UI 一致性。
代码示例
下面的副作用应放在 effect 中,而不是组件渲染体里直接执行。
TSX
function Profile({ userId }: { userId: string }) {
useEffect(() => {
logPageView(userId)
}, [userId])
return <section>用户:{userId}</section>
}常见误区
- 在组件函数执行过程中发请求、写 localStorage 或修改全局变量。
- 认为 useEffect 和 useLayoutEffect 都在同一个时机执行。
- 不知道渲染阶段可能被中断,导致并发模式下副作用重复或错乱。