React 执行阶段与渲染机制详解(基于 React 18+ 官方文档)

React 执行阶段与渲染机制详解(基于 React 18+ 官方文档)

🌟 核心概念:React 的执行流程分层

React 的工作流程基于 Fiber 架构 ,将任务拆分为可中断的单元,核心分为 Render Phase(渲染阶段)Commit Phase(提交阶段) ,并辅以 副作用阶段卸载阶段。以下是详细解析:


一、Render Phase(渲染阶段 / 协调阶段)

1. 作用与触发

  • 目的:计算新的 Virtual DOM 树,并与旧树进行 Diff(协调算法),决定需要更新的部分。
  • 触发条件
    • 初始挂载(Mount)
    • 状态更新(State Update):useState/useReducer
    • Props 变化(父组件重渲染)
    • 强制更新(forceUpdate

2. 特性

  • 纯函数性 :组件函数必须是纯函数,禁止修改外部状态或变量 (如 propsstate、全局变量)。
  • 可中断性:React 18 的并发模式下,此阶段可被中断或重启,优先处理高优先级任务。
  • Strict Mode 行为 :开发环境下,React 会双调用组件函数,用于检测非纯函数导致的副作用。

3. 代码示例

jsx 复制代码
function Counter({ time }) {
  // 纯函数:相同输入返回相同 JSX
  return (
    <>
      <h1>{time}</h1>
      <input /> {/* 用户输入不会因父组件重渲染而丢失 */}
    </>
  );
}

二、Commit Phase(提交阶段)

1. 作用

将 Render Phase 计算出的变更同步应用到真实 DOM,确保用户界面即时更新。

2. 三个子阶段

  1. Before Mutation
    • 执行 getSnapshotBeforeUpdate(类组件)
    • 执行 useLayoutEffect清理函数
  2. Mutation
    • 实际插入、更新、删除 DOM 节点
  3. Layout
    • 执行 useLayoutEffect创建函数
    • 类组件的 componentDidMount/componentDidUpdate

3. 关键特性

  • 不可中断:此阶段必须一次性完成,确保 DOM 操作的原子性。
  • 避免闪烁 :React 仅更新差异节点(Diff 结果),保证 input 值等用户交互状态不丢失。

三、Passive Effect Phase(被动副作用阶段)

1. 作用

在浏览器完成布局和绘制后,异步执行副作用(如网络请求、订阅)。

2. 执行内容

  • useEffect 的创建函数和清理函数
  • 类组件的 componentDidMount/componentDidUpdate/componentWillUnmount 中的异步操作

3. 与 useLayoutEffect 的区别

Hook 执行时机 是否阻塞渲染 适用场景
useEffect Passive Phase ❌ 否 数据获取、日志、非关键副作用
useLayoutEffect Commit Phase(Layout 阶段) ✅ 是 同步 DOM 操作(如测量尺寸)

四、Unmount Phase(卸载阶段)

1. 触发条件

组件从 DOM 中移除(如条件渲染切换、列表项删除)。

2. 执行内容

  • 清理 useEffect/useLayoutEffect 的副作用
  • 类组件的 componentWillUnmount

五、状态保留与重置机制

1. 状态隔离规则

  • 相同位置保留状态 :组件在树中的位置不变时,React 保留其 state
  • 位置变化重置状态:组件位置变化时,React 会销毁旧组件并初始化新组件(即使类型相同)。

2. 控制状态保留的技巧

  • Key 属性 :通过唯一 key 标识列表项,避免位置变化导致的状态重置。
  • 条件渲染:动态切换组件类型时,状态会被重置(即使 props 相同)。
jsx 复制代码
function App() {
  const [isFancy, setIsFancy] = useState(false);
  return (
    <div>
      {isFancy ? <Counter isFancy={true} /> : <Counter isFancy={false} />}
    </div>
  );
}

上述示例中,<Counter /> 的位置不变,因此 score 状态会保留。


六、错误处理机制(Error Boundaries)

1. 执行阶段

  • getDerivedStateFromError:同步执行,用于渲染降级 UI。
  • componentDidCatch:提交阶段执行,用于记录错误日志。

2. 限制

  • 无法捕获的错误 :事件处理器、异步代码(如 setTimeout)、服务端渲染(SSR)中的错误。

七、性能优化策略

1. 避免过早优化

  • 默认行为:React 的 Diff 算法已足够高效,优先保证代码可读性。
  • 优化时机 :当性能瓶颈明显时,使用 React.memouseMemouseCallback 等工具。

2. 优化技巧

  • 减少不必要的 re-renders :使用 React.memo 包裹子组件。
  • 避免在 Render Phase 创建对象/函数 :使用 useMemo/useCallback 缓存。
  • 并发模式下的优先级调度:React 自动优化任务优先级,无需手动干预。

八、官方文档与术语参考


九、总结:React 执行流程全貌

csharp 复制代码
用户交互 / 状态更新
        ↓
   [Render Phase](协调)
        ↓
   [Commit Phase]
   ├── Before Mutation → useInsertionEffect / getSnapshotBeforeUpdate
   ├── Mutation        → DOM 更新
   └── Layout          → useLayoutEffect / componentDidMount/Update
        ↓
[Passive Effect Phase] → useEffect
        ↓
[Unmount Phase] → 清理副作用

掌握这一流程,能帮助你编写更符合 React 设计哲学的代码,避免常见陷阱(如非纯函数、滥用 useLayoutEffect),并充分利用 React 的并发能力提升应用性能。

相关推荐
夏幻灵40 分钟前
HTML5里最常用的十大标签
前端·html·html5
Mr Xu_1 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js
未来龙皇小蓝1 小时前
RBAC前端架构-01:项目初始化
前端·架构
程序员agions1 小时前
2026年,微前端终于“死“了
前端·状态模式
万岳科技系统开发1 小时前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
程序员猫哥_1 小时前
HTML 生成网页工具推荐:从手写代码到 AI 自动生成网页的进化路径
前端·人工智能·html
龙飞051 小时前
Systemd -systemctl - journalctl 速查表:服务管理 + 日志排障
linux·运维·前端·chrome·systemctl·journalctl
我爱加班、、1 小时前
Websocket能携带token过去后端吗
前端·后端·websocket
AAA阿giao1 小时前
从零拆解一个 React + TypeScript 的 TodoList:模块化、数据流与工程实践
前端·react.js·ui·typescript·前端框架
杨超越luckly1 小时前
HTML应用指南:利用GET请求获取中国500强企业名单,揭秘企业增长、分化与转型的新常态
前端·数据库·html·可视化·中国500强