前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库React 18 React 17 异步自动批处理 createRoot
ReReact状态与渲染

React 18 的异步自动批处理与 React 17 有什么区别,为什么还要看根 API?

迁移到 React 18 时,版本号和根的创建方式共同决定是否采用新的自动批处理行为。

前端进阶之旅 · 一题精讲更新于 2026.09.06
React#状态与渲染#异步编程
先看核心答案读代码示例
理解线索

比较前先固定实验条件

  1. 运行版本明确 React 与 React DOM 的具体配套版本
  2. 创建根方式区分现代 createRoot 与历史 render 入口
  3. 观测提交隔离挂载和点击,只比较同一回调产生的更新

组件可在不同版本夹具中复用;旧版比较只用于解释历史行为,不建议在新项目恢复旧根 API。

核心回答

先记住这个答案

React 17 通常只在 React 管理的事件处理过程中自动批处理,Promise、定时器等回调里的多个更新常产生独立提交。React 18 使用 createRoot 的新根后,把自动批处理扩展到这些来源;仅升级包却继续使用旧 ReactDOM.render,会保留旧式行为,不能据此判断新功能失效。这里比较普通更新,不把整段跨多个 await 的业务流程说成一个不可分割批次,也不把不同有意点击默认合并。后续现代 React 根继续采用这种更新模型。

  • 版本与 createRoot 入口需要一起核对
  • Promise 和定时器内的相邻更新可自动批处理
  • 跨异步阶段的整项业务不等于一个批次

同一个异步回调更新两个状态时会怎样

下面一个回调同时增加计数并切换开关,分别由 Promise 与定时器触发。使用现代根时,普通情况下会直接提交这一轮的完整组合;旧式根可能先提交计数变化,再提交开关变化,产生中间组合。

测量时让一次操作完成后再触发另一种来源,并关闭 Strict Mode 或明确排除其开发检查影响。不能让网络请求、其他组件状态和热更新混入实验,再把所有提交次数差异都归因于自动批处理。

用同一组更新比较两个异步来源TSX
import { useState } from 'react';

export default function AsyncBatching() {
  const [count, setCount] = useState(0);
  const [active, setActive] = useState(false);
  function updateBoth() {
    setCount(value => value + 1);
    setActive(value => !value);
  }
  return <>
    <button onClick={() => Promise.resolve().then(updateBoth)}>Promise 更新</button>
    <button onClick={() => setTimeout(updateBoth, 0)}>定时器更新</button>
    <output>{count} / {active ? '开启' : '关闭'}</output>
  </>;
}

先点 Promise 再点定时器,最终依次显示一与开启、二与关闭。版本差异主要体现在中间提交,而不是最终算术结果;需要结合根 API 和提交观测判断。

升级包后仍看到旧行为应先查入口

React 18 提供旧入口兼容迁移,使团队能分阶段切换。排查时确认真正挂载这个组件的根,而不是只在 package.json 看到版本十八;微前端或多个根的应用还可能混用不同入口。

React 19 已不再保留旧 render 作为常规可用入口,新项目应按当前官方 API 创建根。迁移测试应检查依赖同步读取 DOM 的代码是否暴露问题,而不是仅把计数日志从两条变成一条就宣布迁移完成。

自动批处理不能保证所有异步步骤一起完成

async 函数在 await 前后可能处于不同调度阶段,不能假定启动时设置 loading 与远端结果返回时写入数据永远只提交一次。业务本来就可能需要先显示加载状态,再显示结果,强行追求一次提交反而会破坏反馈。

若第三方同步接口要求立即读取刚更新的 DOM,可以审慎使用 flushSync,但这会主动改变正常安排并可能增加工作量。自动批处理也不会防止请求重复、恢复失败或过期结果覆盖,这些仍属于异步任务和状态建模的问题。

回答前,多想一步

容易答错的地方

只要装上 React 18,所有旧入口都会自动变成新行为
React 18 的根入口会影响迁移模式,必须核对实际挂载代码;不能只依据依赖版本就推断 Promise 回调中一定如何提交。
一个 async 函数里的所有更新永远只提交一次
await 会把流程拆成多个阶段,其他调度也可能介入。应按实际异步边界和用户反馈需求设计状态,不能依靠过强的提交次数假设。
试着用自己的话回答

面试官还会怎么问?

为什么现代根里仍可能看到两条组件日志?

开发检查、其他更新或渲染尝试都可能产生额外调用,日志不是提交次数。应隔离实验并使用提交阶段观测,确认究竟有哪些界面结果被发布。

自动批处理会改变 updater 的先后含义吗?

不会把相对更新变成任意顺序。updater 仍依据队列语义组合,变化主要在适合一起处理的更新如何安排渲染与提交。

旧代码立即读取 DOM 失败时应先怎么处理?

先确认是否本应在提交后执行,以及能否调整集成流程。只有同步外部接口确实要求当前调用栈拿到新 DOM 时,再考虑有限使用 flushSync。

从一道题,走向一组知识

把知识连起来

状态与渲染

React 事件里的多个 setState 怎样批处理,为什么不能只数 render 日志?

先理解普通 React 事件中的更新批处理

状态与渲染

React flushSync 什么时候有必要,为什么它不会让旧闭包变成新状态?

同步外部接口需要明确的提交边界与成本

参考资料

  • React 18:Automatic batching
  • React 19:Removed ReactDOM.render

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 同一个异步回调更新两个状态时会怎样
  3. 升级包后仍看到旧行为应先查入口
  4. 自动批处理不能保证所有异步步骤一起完成
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑