Skip to content

React 状态更新与渲染原理最小实现

这篇文档不追求完整还原 React 源码,而是聚焦面试里最常被问到的那条主线: setState/useState 是如何触发更新的,Fiber 架构是什么,以及 reconciliation 和 scheduler 如何协同工作。

一、核心要点速览

💡 核心考点

  • React 没有响应式系统:React 通过显式的状态更新(setState)触发重新渲染,而非自动依赖追踪。
  • Fiber 架构:将渲染过程拆分为可中断的增量任务单元,支持优先级调度。
  • Reconciliation(协调):通过 Diff 算法比较虚拟 DOM 树,找出最小变化集。
  • Scheduler(调度器):基于时间切片(Time Slicing)和优先级队列管理任务执行。
  • 双缓冲机制:使用 current 树和 workInProgress 树避免页面闪烁。

二、整体流程图

下面这张图专门对应本文的"最小实现版"代码,用来串起从状态更新到视图渲染的完整链路:

React 状态更新最小实现流程图

可以先记住这两条主线:

  • 初始化链路createElement -> render -> Fiber 构建 -> commit -> DOM 更新
  • 更新链路setState -> 创建更新 -> 调度任务 -> reconcile -> commit -> DOM 更新

三、核心实现代码(精简版)

js
/* ================= 基础数据结构 ================= */

// Fiber 节点结构
class FiberNode {
  constructor(tag, pendingProps, key) {
    this.tag = tag // 组件类型:'host'(DOM元素)、'function'(函数组件)、'class'(类组件)
    this.key = key
    this.elementType = null // 元素类型(div、Component等)
    this.type = null // 实际类型(与 elementType 相同,但用于 lazy 组件等)
    this.stateNode = null // 真实 DOM 节点或组件实例
    
    // Fiber 链表
    this.return = null // 父节点
    this.child = null // 第一个子节点
    this.sibling = null // 下一个兄弟节点
    
    // 状态和属性
    this.pendingProps = pendingProps // 待处理的 props
    this.memoizedProps = null // 已记忆的 props
    this.memoizedState = null // 已记忆的状态(用于 useState)
    
    // 副作用
    this.flags = 0 // 副作用标记(增删改)
    this.subtreeFlags = 0 // 子树的副作用
    this.deletions = null // 待删除的子节点
    
    // 优先级
    this.lanes = 0 // 当前任务的优先级
    this.childLanes = 0 // 子树的优先级
  }
}

// 更新对象结构
class Update {
  constructor(payload) {
    this.payload = payload // 更新内容(新状态或函数)
    this.next = null // 链表指针
  }
}

// 更新队列
class UpdateQueue {
  constructor() {
    this.shared = { pending: null } // 环形链表
  }
}

/* ================= 全局变量 ================= */
let root = null // Fiber 根节点
let workInProgress = null // 当前正在工作的 Fiber
let nextUnitOfWork = null // 下一个工作单元
let committedRoot = null // 已提交的根节点

/* ================= 状态管理(useState 核心) ================= */

// 创建更新队列
function initializeUpdateQueue() {
  return new UpdateQueue()
}

// 创建更新对象
function createUpdate(payload) {
  return new Update(payload)
}

// 将更新加入队列
function enqueueUpdate(fiber, update) {
  const updateQueue = fiber.updateQueue
  if (!updateQueue) {
    fiber.updateQueue = new UpdateQueue()
  }
  
  const sharedQueue = fiber.updateQueue.shared
  const pending = sharedQueue.pending
  
  if (pending === null) {
    // 队列为空,形成环
    update.next = update
  } else {
    // 插入到环的末尾
    update.next = pending.next
    pending.next = update
  }
  
  sharedQueue.pending = update
}

// 处理更新队列,计算新状态
function processUpdateQueue(fiber) {
  const updateQueue = fiber.updateQueue
  if (!updateQueue) return
  
  const sharedQueue = updateQueue.shared
  let pending = sharedQueue.pending
  
  if (pending === null) return
  
  // 解开环形链表
  const firstUpdate = pending.next
  pending.next = null
  
  let update = firstUpdate
  let newState = fiber.memoizedState
  
  // 遍历所有更新
  while (update !== null) {
    const payload = update.payload
    
    if (typeof payload === 'function') {
      // 函数式更新:setState(prev => prev + 1)
      newState = payload(newState)
    } else {
      // 直接赋值:setState(newValue)
      newState = payload
    }
    
    update = update.next
  }
  
  // 保存新状态
  fiber.memoizedState = newState
}

// useState 实现
function useState(initialValue) {
  const currentFiber = workInProgress
  
  // 首次渲染:初始化状态
  if (!currentFiber.memoizedState) {
    currentFiber.memoizedState = initialValue
    currentFiber.updateQueue = new UpdateQueue()
  }
  
  // setState 函数
  const setState = (action) => {
    const update = createUpdate(action)
    enqueueUpdate(currentFiber, update)
    
    // 调度更新
    scheduleUpdateOnFiber(currentFiber)
  }
  
  return [currentFiber.memoizedState, setState]
}

/* ================= 调度器(Scheduler) ================= */

// 优先级常量
const SyncLane = 1 // 同步优先级(最高)
const InputContinuousLane = 2 // 用户输入优先级
const DefaultLane = 4 // 默认优先级
const IdleLane = 8 // 空闲优先级(最低)

// 调度更新
function scheduleUpdateOnFiber(fiber) {
  // 标记为需要同步更新
  fiber.lanes = SyncLane
  
  // 从根节点开始调度
  const root = markUpdateLaneFromFiberToRoot(fiber)
  
  // 进入调度循环
  performSyncWorkOnRoot(root)
}

// 向上遍历 Fiber 树,标记优先级
function markUpdateLaneFromFiberToRoot(sourceFiber) {
  let node = sourceFiber
  let parent = node.return
  
  while (parent !== null) {
    parent.childLanes |= node.lanes
    node = parent
    parent = node.return
  }
  
  return node // 返回根节点
}

// 同步工作入口
function performSyncWorkOnRoot(root) {
  // 确保从根节点开始工作
  ensureRootIsScheduled(root)
  
  // 执行工作循环
  workLoopSync()
  
  // 提交更改
  commitRoot()
}

// 工作循环(不可中断版本)
function workLoopSync() {
  while (nextUnitOfWork !== null) {
    nextUnitOfWork = performUnitOfWork(nextUnitOfWork)
  }
}

// 异步工作循环(可中断版本 - 简化)
function workLoopConcurrent() {
  // 检查是否有剩余时间
  while (nextUnitOfWork !== null && !shouldYield()) {
    nextUnitOfWork = performUnitOfWork(nextUnitOfWork)
  }
}

// 判断是否应该让出控制权(时间切片)
function shouldYield() {
  // 简化版:检查当前时间是否超过 deadline
  return false // 实际实现会使用 MessageChannel 或 requestIdleCallback
}

/* ================= Reconciliation(协调) ================= */

// 执行一个工作单元
function performUnitOfWork(unitOfWork) {
  const current = unitOfWork.alternate // 获取对应的旧 Fiber
  
  // Begin 阶段:处理当前节点
  let next = beginWork(current, unitOfWork)
  
  // Complete 阶段:处理完子树后
  unitOfWork.memoizedProps = unitOfWork.pendingProps
  
  if (unitOfWork.child === null) {
    // 没有子节点,向上回溯
    return completeUnitOfWork(unitOfWork)
  }
  
  // 有子节点,继续处理子节点
  return unitOfWork.child
}

// Begin Work:创建子 Fiber
function beginWork(current, workInProgress) {
  switch (workInProgress.tag) {
    case 'host': // DOM 元素
      return updateHostComponent(current, workInProgress)
    case 'function': // 函数组件
      return updateFunctionComponent(current, workInProgress)
    case 'class': // 类组件
      return updateClassComponent(current, workInProgress)
    default:
      return null
  }
}

// 处理 DOM 元素
function updateHostComponent(current, workInProgress) {
  // 确保有子 Fiber
  reconcileChildren(current, workInProgress)
  return workInProgress.child
}

// 处理函数组件
function updateFunctionComponent(current, workInProgress) {
  const type = workInProgress.type // 组件函数
  const props = workInProgress.pendingProps
  
  // 重置当前工作的 Fiber
  workInProgress = workInProgress
  
  // 执行组件函数,获取 JSX
  let children
  try {
    children = type(props)
  } catch (error) {
    console.error('组件渲染错误:', error)
  }
  
  // 协调子节点
  reconcileChildren(current, workInProgress, children)
  
  return workInProgress.child
}

// 处理类组件
function updateClassComponent(current, workInProgress) {
  const instance = workInProgress.stateNode
  
  if (instance === null) {
    // 首次挂载:创建实例
    constructClassInstance(workInProgress)
  } else {
    // 更新:调用 render
    finishClassComponent(current, workInProgress, instance)
  }
  
  return workInProgress.child
}

// 协调子节点(Diff 算法核心)
function reconcileChildren(current, workInProgress, newChildren) {
  if (newChildren === null || newChildren === undefined) {
    return
  }
  
  // 简化版:只处理单个子节点
  if (typeof newChildren === 'object' && !Array.isArray(newChildren)) {
    const childFiber = createFiberFromElement(newChildren)
    childFiber.return = workInProgress
    workInProgress.child = childFiber
  }
}

// 从 React 元素创建 Fiber
function createFiberFromElement(element) {
  const { type, props, key } = element
  
  let tag
  if (typeof type === 'string') {
    tag = 'host' // DOM 元素
  } else if (typeof type === 'function') {
    tag = 'function' // 函数组件
  } else if (typeof type === 'object' && type.isReactComponent) {
    tag = 'class' // 类组件
  }
  
  const fiber = new FiberNode(tag, props, key)
  fiber.elementType = type
  fiber.type = type
  
  return fiber
}

// Complete Work:收集副作用
function completeUnitOfWork(unitOfWork) {
  let siblingFiber = unitOfWork.sibling
  
  // 如果有兄弟节点,处理它
  if (siblingFiber !== null) {
    return siblingFiber
  }
  
  // 否则向上回溯到父节点
  let node = unitOfWork
  let parent = node.return
  
  while (parent !== null) {
    // 检查父节点是否有兄弟
    siblingFiber = parent.sibling
    if (siblingFiber !== null) {
      return siblingFiber
    }
    
    node = parent
    parent = node.return
  }
  
  // 回到根节点,结束
  return null
}

/* ================= Commit(提交) ================= */

// 提交根节点的更改
function commitRoot() {
  const finishedWork = root.current.alternate
  
  // 遍历 Fiber 树,执行 DOM 操作
  commitPassiveMountOnFiber(root, finishedWork)
  
  // 更新 current 指针
  root.current = finishedWork
}

// 提交挂载
function commitPassiveMountOnFiber(root, finishedWork) {
  switch (finishedWork.tag) {
    case 'host':
      commitHostMount(finishedWork)
      break
    case 'function':
      commitFunctionComponentMount(finishedWork)
      break
  }
  
  // 递归处理子节点
  if (finishedWork.child !== null) {
    commitPassiveMountOnFiber(root, finishedWork.child)
  }
}

// 挂载 DOM 元素
function commitHostMount(fiber) {
  const { type, pendingProps } = fiber
  
  // 创建真实 DOM
  const domElement = document.createElement(type)
  
  // 设置属性
  Object.keys(pendingProps).forEach(key => {
    if (key !== 'children') {
      domElement.setAttribute(key, pendingProps[key])
    }
  })
  
  // 处理子节点
  if (pendingProps.children) {
    const textNode = document.createTextNode(pendingProps.children)
    domElement.appendChild(textNode)
  }
  
  // 保存 DOM 引用
  fiber.stateNode = domElement
  
  // 添加到父节点
  if (fiber.return && fiber.return.stateNode) {
    fiber.return.stateNode.appendChild(domElement)
  }
}

/* ================= 工具函数 ================= */

// 确保根节点被调度
function ensureRootIsScheduled(root) {
  if (nextUnitOfWork === null) {
    nextUnitOfWork = root.current.alternate
  }
}

// 创建根节点
function createRoot(container) {
  const hostRootFiber = new FiberNode('host', {}, null)
  hostRootFiber.stateNode = container
  
  root = {
    current: hostRootFiber,
    containerInfo: container,
    pendingChildren: null,
    lanes: 0,
  }
  
  return root
}

// 渲染入口
function render(element, container) {
  const root = createRoot(container)
  
  // 创建根 Fiber 的备用副本(双缓冲)
  const alternate = new FiberNode('host', {}, null)
  alternate.elementType = 'div'
  alternate.type = 'div'
  alternate.stateNode = container
  
  root.current.alternate = alternate
  alternate.alternate = root.current
  
  // 设置初始工作单元
  nextUnitOfWork = alternate
  
  // 开始工作循环
  workLoopSync()
  
  // 提交
  commitRoot()
}

/* ================= JSX 支持 ================= */

// createElement 简化实现
function createElement(type, config, ...children) {
  const props = {}
  
  for (const propName in config) {
    if (config.hasOwnProperty(propName) && propName !== 'key') {
      props[propName] = config[propName]
    }
  }
  
  if (children.length === 1) {
    props.children = children[0]
  } else if (children.length > 1) {
    props.children = children
  }
  
  return {
    $$typeof: Symbol.for('react.element'),
    type,
    key: config?.key || null,
    props,
  }
}

/* ================= 类组件支持 ================= */

// 类组件基类
class Component {
  constructor(props) {
    this.props = props
    this.state = {}
    this.updater = {
      enqueueSetState: (fiber, payload) => {
        const update = createUpdate(payload)
        enqueueUpdate(fiber, update)
        scheduleUpdateOnFiber(fiber)
      }
    }
  }
  
  setState(partialState) {
    this.updater.enqueueSetState(this._fiber, partialState)
  }
}

// 构造类组件实例
function constructClassInstance(fiber) {
  const Component = fiber.type
  const props = fiber.pendingProps
  
  const instance = new Component(props)
  instance._fiber = fiber
  fiber.stateNode = instance
  
  // 调用 render
  const renderResult = instance.render()
  reconcileChildren(null, fiber, renderResult)
}

// 完成类组件更新
function finishClassComponent(current, workInProgress, instance) {
  // 调用 render
  const nextChildren = instance.render()
  reconcileChildren(current, workInProgress, nextChildren)
}

四、JSX 如何转成虚拟 DOM

React 不会直接解析 JSX 语法,而是通过编译器(如 Babel)将 JSX 转换为 createElement 调用。

1. JSX 写法

jsx
<div className="app">
  <h1>Hello React</h1>
  <Counter />
</div>

2. 编译后的 JavaScript

js
React.createElement(
  'div',
  { className: 'app' },
  React.createElement('h1', null, 'Hello React'),
  React.createElement(Counter, null)
)

3. 生成的虚拟 DOM 结构

js
{
  $$typeof: Symbol.for('react.element'),
  type: 'div',
  props: {
    className: 'app',
    children: [
      {
        $$typeof: Symbol.for('react.element'),
        type: 'h1',
        props: { children: 'Hello React' }
      },
      {
        $$typeof: Symbol.for('react.element'),
        type: Counter,
        props: {}
      }
    ]
  }
}

这里最关键的是 type 字段:

  • 如果是字符串(如 'div'),表示原生 DOM 元素
  • 如果是函数(如 Counter),表示自定义组件

五、运行示例

结合上面的最小实现代码,可以这样模拟一次完整的初始化与更新过程:

js
// 定义计数器组件
function Counter({ initialCount }) {
  const [count, setCount] = useState(initialCount || 0)
  
  return createElement(
    'div',
    { id: 'counter' },
    createElement('p', null, `Count: ${count}`),
    createElement('button', { 
      onclick: () => setCount(count + 1) 
    }, 'Increment')
  )
}

// 初始化渲染
const container = document.getElementById('root')
render(createElement(Counter, { initialCount: 0 }), container)

// 模拟点击按钮触发更新
setTimeout(() => {
  // 找到 button 元素并触发点击
  const button = container.querySelector('button')
  button.click()
  
  // 👉 setState 被调用
  // 👉 创建 Update 对象并加入队列
  // 👉 调度器安排任务
  // 👉 Reconciliation 比较变化
  // 👉 Commit 阶段更新 DOM
  // 👉 页面显示 "Count: 1"
}, 1000)

这个示例里,第一次会触发初始化渲染;1 秒后点击按钮,就会走一遍完整的更新链路。


六、执行流程拆解

1. 初始化阶段:Fiber 树是怎么构建的?

text
render(<App />, container)
-> 创建 Root Fiber
-> 创建 workInProgress 树(双缓冲)
-> performUnitOfWork(App)
-> 执行 App 组件函数
-> 遇到子组件 <Header />
-> 创建 Header Fiber 节点
-> 继续处理 Header 的子节点
-> ...(递归构建整棵树)
-> completeUnitOfWork 回溯
-> commitRoot() 将 Fiber 转为真实 DOM
-> container.appendChild(domElement)

这一阶段的重点是:

  • Begin 阶段向下构建:从根节点开始,逐个创建子 Fiber 节点。
  • Complete 阶段向上回溯:当子节点处理完毕,回到父节点收集副作用。
  • Commit 阶段操作 DOM:只有在这个阶段才会真正修改浏览器 DOM。

所以本质上不是"一次性生成 DOM",而是"分阶段增量构建 Fiber 树,最后批量提交"。


2. 更新阶段:setState 后发生了什么?

text
setState(newValue)
-> 创建 Update 对象
-> 加入 Fiber.updateQueue(环形链表)
-> scheduleUpdateOnFiber(fiber)
-> 向上遍历标记优先级(fiber.lanes)
-> performSyncWorkOnRoot(root)
-> workLoopSync() 开始工作循环
-> performUnitOfWork(fiber) 处理每个节点
-> beginWork() 对比新旧 props
-> 发现变化,标记 flags(Placement/Update/Deletion)
-> completeUnitOfWork() 收集子树副作用
-> commitRoot() 提交更改
-> 根据 flags 执行 DOM 操作
-> 更新完成,页面刷新

这一阶段的重点是:

  • Update 入队:setState 不直接修改状态,而是创建更新对象放入队列。
  • 优先级调度:根据 lanes 模型决定哪些更新优先执行。
  • Reconcile 对比:通过 Diff 算法找出最小变化集,避免全量更新。
  • Commit 批量提交:将所有 DOM 操作集中在 Commit 阶段执行,减少重排重绘。

七、角色分工

1. Fiber 节点是干什么的?

  • Fiber 是虚拟 DOM 的升级版,每个节点代表一个工作单元。
  • 它包含组件的类型、状态、props、副作用等信息。
  • 通过 child/sibling/return 三个指针形成链表结构,支持增量遍历。
  • 双缓冲机制:current 树对应当前屏幕显示,workInProgress 树对应正在构建的新树。

2. Scheduler 是干什么的?

  • Scheduler 负责任务调度和优先级管理。
  • 高优先级任务(如同步更新)立即执行,低优先级任务(如空闲回调)延迟执行。
  • 支持时间切片(Time Slicing):将大任务拆分为多个小任务,每帧执行一部分,避免阻塞浏览器。
  • 使用 requestIdleCallbackMessageChannel 实现异步可中断。

3. Reconciliation 做了什么?

  • Reconciliation 负责比较新旧虚拟 DOM 树,找出差异。
  • 采用启发式 O(n) 算法,基于两个假设:
    1. 不同类型的元素产生不同的树
    2. 开发者可以通过 key prop 提示哪些子元素稳定
  • 对比策略:
    • 单节点 Diff:快速路径,大部分场景适用
    • 多节点 Diff:处理列表,通过 key 优化复用

八、Vue3 vs React 响应式对比

特性Vue3(响应式系统)React(状态驱动)
更新触发自动依赖追踪,数据修改即触发手动调用 setState/useState
细粒度更新✅ 精确到组件内部的数据绑定❌ 组件级别更新,需手动优化
学习成本较低,模板语法直观较高,需理解 Hooks、闭包等概念
性能优化自动优化,无需手动干预需要 useCallback、useMemo、React.memo
调试难度较容易,依赖关系清晰较困难,需 DevTools 分析渲染原因
灵活性受限于响应式系统极高,完全控制渲染逻辑
Tree Shaking较难,响应式代码全量打包容易,未使用的代码可移除
服务端渲染需要特殊处理响应式状态天然支持,纯函数渲染

九、Class vs Function 组件对比

特性Class ComponentFunction Component + Hooks
语法复杂度较高,需要理解 this、生命周期较低,纯函数更直观
逻辑复用HOC/Render Props,嵌套严重自定义 Hooks,扁平组合
状态管理this.state,对象形式useState,独立状态变量
副作用处理componentDidMount/Update/Unmount 分散useEffect 聚合相关逻辑
闭包陷阱不存在⚠️ 需要注意依赖数组
性能优化shouldComponentUpdateReact.memo + useMemo
错误边界✅ 支持 componentDidCatch❌ 暂不支持
推荐程度遗留项目✅ 新项目首选

💡 最佳实践

  • 优先使用 Function + Hooks:代码更简洁,逻辑复用更方便。
  • 避免在渲染中创建新引用:使用 useCallback/useMemo 缓存函数和对象。
  • 合理拆分组件:小组件更容易优化和理解。
  • 使用 ESLint 插件:自动检测 Hooks 依赖问题。

十、面试高频回答

1. React 为什么不像 Vue 那样做响应式?

答: React 的设计理念是"显式优于隐式":

  1. 可控性更强:开发者明确知道何时触发更新,便于调试和优化。
  2. 灵活性更高:不受响应式系统限制,可以完全控制渲染逻辑。
  3. Tree Shaking 友好:未使用的代码可以被移除,减小打包体积。
  4. SSR 天然支持:纯函数渲染不需要处理响应式状态的序列化。
  5. 历史原因:React 诞生时 Proxy 还未普及,Object.defineProperty 性能较差。

2. Fiber 架构解决了什么问题?

答: Fiber 主要解决了两个问题:

  1. 可中断渲染:传统 Stack Reconciler 一旦开始无法中断,导致主线程阻塞。Fiber 将任务拆分为可中断的小单元,支持增量渲染。
  2. 优先级调度:不同更新可以有不同优先级(如同步、异步、空闲),高优先级任务可以打断低优先级任务。

3. Reconciliation 的 Diff 算法复杂度是多少?

答:

  • 理论复杂度:O(n³),因为需要比较所有节点的所有可能变化。
  • 实际复杂度:O(n),通过两个假设优化:
    1. 不同类型的元素产生不同的树(遇到不同类型直接替换,不再比较子节点)
    2. 通过 key prop 识别稳定节点(列表复用优化)
  • 单节点 Diff:大多数场景只需比较一次,接近 O(1)。
  • 多节点 Diff:列表场景通过 key 映射,接近 O(n)。

4. 一句话概括整条链路?

答: setState 创建更新并入队,调度器安排任务,Reconciliation 找出差异,Commit 批量更新 DOM。


十一、最终总结

text
初始化:
createElement -> render -> Fiber 构建(Begin/Complete)-> commit -> DOM 挂载

更新:
setState -> 创建 Update -> 加入队列 -> 调度任务 -> workLoop -> reconcile(Diff)-> commit -> DOM 更新

最需要记住的一句话是:

React 通过显式的状态更新触发渲染,Fiber 架构将渲染过程拆分为可中断的增量任务,配合优先级调度和 Diff 算法,实现了高性能的 UI 更新。


十二、扩展阅读

1. 并发模式(Concurrent Mode)

React 18 引入的并发特性,核心能力包括:

  • useTransition:标记非紧急更新,允许被紧急更新打断
  • useDeferredValue:延迟更新某些值,类似防抖
  • Suspense:声明式等待异步数据,自动显示 fallback
  • 批量更新优化:自动批量化多个 setState 调用

2. 性能优化技巧

js
// 1. 避免不必要的重渲染
const MemoizedChild = React.memo(Child)

// 2. 缓存回调函数
const handleClick = useCallback(() => {
  doSomething(id)
}, [id])

// 3. 缓存计算结果
const expensiveValue = useMemo(() => {
  return computeExpensive(data)
}, [data])

// 4. 代码分割
const LazyComponent = React.lazy(() => import('./HeavyComponent'))

// 5. 虚拟化长列表
import { FixedSizeList } from 'react-window'

3. 常见性能陷阱

js
// ❌ 陷阱 1:内联对象每次都是新引用
<Component style={{ color: 'red' }} />

// ✅ 修复:提取到外部或使用 useMemo
const redStyle = useMemo(() => ({ color: 'red' }), [])
<Component style={redStyle} />


// ❌ 陷阱 2:箭头函数每次都是新引用
<Item onClick={() => handleDelete(id)} />

// ✅ 修复:使用 useCallback
const handleClick = useCallback(() => handleDelete(id), [id])
<Item onClick={handleClick} />


// ❌ 陷阱 3:props 展开导致子组件无效重渲染
<Child {...bigObject} />

// ✅ 修复:只传递必要的字段
<Child name={bigObject.name} age={bigObject.age} />

4. React 18+ 新特性

  • Automatic Batching:自动批量更新,减少重渲染次数
  • Start Transition:标记非紧急更新,提升交互响应速度
  • Server Components:服务端组件,零 bundle 大小的组件
  • use Hook:统一处理 Promise 和 Context,简化异步逻辑

十三、记忆口诀

React 更新歌诀:

React 更新不自动,
setState 来触发它。
Fiber 架构分阶段,
Begin Complete 两步走!

Update 入队别忘记,
调度器管优先级。
Reconcile 找差异,
Diff 算法 O(n) 搞定!

Commit 阶段改 DOM,
批量操作效率高。
双缓冲机制防闪烁,
current workInProgress 两棵树!

并发模式更强大,
时间切片不卡顿。
useTransition 标缓急,
Suspense 等数据!

性能优化三板斧:
memo useCallback useMemo。
避免内联新引用,
合理拆分小组件!

Hooks 虽好别滥用,
依赖数组仔细看。
闭包陷阱要警惕,
ESLint 插件来帮忙!

十四、推荐资源


十五、总结一句话

  • React 核心: 显式状态更新 + Fiber 架构 = 可控的高性能渲染 🎯
  • 调度机制: Scheduler + Lanes 优先级 = 可中断的增量渲染
  • 对比优化: Reconciliation Diff + memo/useMemo = 最小化 DOM 操作
最近更新