React状态更新流程

一、核心概念与场景总结

  1. setState 的同步 / 异步特性
    setState 本身不是单纯的同步或异步 ,其执行时机由 React 的更新上下文决定:
  • 异步场景(React 可控上下文):React 合成事件(onClick/onChange)、生命周期函数(componentDidMount 等)、React 批量更新机制触发时,setState 是 "异步" 的(实际是延迟执行 + 批量更新)。

  • 同步场景(React 不可控上下文):原生事件(addEventListener)、setTimeout/setInterval、Promise.then/catch、手动调用 DOM 事件等,setState 是同步执行的。

示例代码:

js 复制代码
import React, { useState, useEffect } from 'react';

const StateDemo = () => {
  const [count, setCount] = useState(0);

  // 1. React 合成事件(异步)
  const handleReactClick = () => {
    setCount(count + 1);
    console.log('合成事件中:', count); // 输出旧值 0(异步未更新)
  };

  // 2. 生命周期等效逻辑(异步)+ 原生事件 / 定时器(同步)
  useEffect(() => {
    // 原生事件(同步)
    const nativeBtn = document.getElementById('native-btn');
    const handleNativeClick = () => {
      setCount(prev => prev + 1);
      console.log('原生事件中:', count); // 输出新值(同步更新)
    };
    nativeBtn.addEventListener('click', handleNativeClick);

    // 3. setTimeout(同步)
    setTimeout(() => {
      setCount(prev => prev + 1);
      console.log('setTimeout 中:', count); // 输出新值(同步更新)
    }, 0);

    // 4. useEffect 等效生命周期(异步)
    setCount(count + 1);
    console.log('useEffect 中:', count); // 输出旧值 0

    // 解绑事件
    return () => nativeBtn.removeEventListener('click', handleNativeClick);
  }, []);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleReactClick}>React 合成事件</button>
      <button id="native-btn">原生事件</button>
    </div>
  );
};

export default StateDemo;

2. dispatchAction 更新链路(核心流程)

dispatchAction 是 React 状态更新的入口,完整链路如下:

关键源码片段(简版)

js 复制代码
// 1. dispatchAction 入口(ReactFiberClassComponent.js)
function dispatchAction(fiber, queue, action) {
  // 创建 Update 对象
  const update = {
    action,
    lane: requestUpdateLane(fiber), // 优先级
    next: null,
  };

  // 将 Update 加入队列
  const pending = queue.pending;
  if (pending === null) {
    update.next = update;
  } else {
    update.next = pending.next;
    pending.next = update;
  }
  queue.pending = update;

  // 调度更新
  scheduleUpdateOnFiber(fiber, update.lane);
}

// 2. 调度更新(ReactFiberWorkLoop.js)
function scheduleUpdateOnFiber(fiber, lane) {
  // 标记更新优先级
  markUpdateLaneFromFiberToRoot(fiber, lane);
  // 判断是否批量更新(核心:batchedUpdates 标记)
  if (isBatchingUpdates) {
    // 批量更新:暂存更新,不立即执行
    if (isUnbatchingUpdates) {
      flushSyncCallbacks(); // 非批量模式下立即执行
    }
    return;
  }

  // 非批量更新:立即调度
  const root = getRootForFiber(fiber);
  scheduleCallback(lanesToEventPriority(lane), () => {
    performSyncWorkOnRoot(root); // 执行同步更新
  });
}

3. 批量更新原理

React 批量更新的核心是 事务 (Transaction) 和 isBatchingUpdates 标记:

  • React 在执行合成事件、生命周期等逻辑时,会先将 isBatchingUpdates 设为 true,此时所有 setState 不会立即触发 DOM 更新,而是将更新请求加入队列;
  • 当事件 / 生命周期执行完成后,React 会将 isBatchingUpdates 设为 false,然后批量处理队列中的所有更新,只触发一次 render 和 commit 阶段,减少 DOM 操作,提升性能。

手动开启 / 关闭批量更新示例

js 复制代码
import React, { useState, useEffect } from 'react';
import { unstable_batchedUpdates } from 'react-dom';

const BatchDemo = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    // 手动开启批量更新
    setTimeout(() => {
      unstable_batchedUpdates(() => {
        setCount(prev => prev + 1);
        setCount(prev => prev + 1);
        console.log('批量更新中:', count); // 输出旧值,最终只更新一次
      });
    }, 0);
  }, []);

  return <div>Count: {count}</div>;
};

export default BatchDemo;

知识点总结

一、setState 同步/异步场景总结

1. 异步场景(React 可控)

  • React 合成事件(onClick、onChange、onSubmit 等)
  • 组件生命周期函数(componentDidMount、componentDidUpdate 等)
  • React 批量更新机制覆盖的场景(如 unstable_batchedUpdates 包裹)
  • 特点:setState 延迟执行,多次调用合并为一次 DOM 更新,this.state 立即获取为旧值

2. 同步场景(React 不可控)

  • 原生 DOM 事件(addEventListener 绑定的事件)
  • 定时器(setTimeout、setInterval)
  • 异步操作(Promise.then/catch、async/await)
  • 手动触发的 DOM 事件(如 element.click())
  • 特点:setState 立即执行,this.state 可立即获取新值

3. 注意事项

  • setState 第二个参数(回调函数)始终能获取最新状态:this.setState({}, () => console.log(this.state.count))
  • 函数式 setState 可避免状态依赖问题:this.setState(prev => ({ count: prev.count + 1 }))

二、总结

  1. setState 特性 :同步/异步由 React 上下文决定,核心是 isBatchingUpdates 标记控制是否批量更新;
  2. dispatchAction 链路:创建 Update → 加入队列 → 调度更新 → render 计算新状态 → commit 更新 DOM;
  3. 批量更新原理:React 通过事务机制将可控上下文的多次 setState 合并为一次 DOM 更新,提升性能。
相关推荐
问心无愧05136 小时前
ctf show web入门160 161
前端·笔记
李小白666 小时前
第四天-WEB服务器基本原理,IIS服务
运维·服务器·前端
humcomm7 小时前
AI编程时代新前端职位
前端·ai编程
好家伙VCC7 小时前
Web Components主题热切换方案揭秘
java·前端
甲维斯7 小时前
Kimi版超级玛丽效果“惊人”,配额不足5厘米!
前端·人工智能
hboot7 小时前
AI工程师第一课 - Python
前端·后端·python
凉菜凉凉7 小时前
AI时代,被抛弃的前端
前端·ai
console.log('npc')8 小时前
AI前端工程与生成式UI学习路线
前端·人工智能·ui
梦曦i8 小时前
uni-router v1.1.1发布:守卫超时保护+路由监听
前端·uni-app
qq_2518364578 小时前
基于java Web网络订餐系统设计与实现 源码文档
java·开发语言·前端