← 返回目录

第 27 卷

第 27 / 28 卷日期:

批处理是 React 用于优化性能的核心机制之一,核心定义是:「将多个状态更新(setState/useState 更新)合并为一次渲染,减少真实 DOM 的操作次数」。

原理:React 中每次状态更新都会触发组件重新渲染(包括虚拟 DOM 对比、真实 DOM 更新),若短时间内多次调用状态更新,会导致多次渲染,产生大量冗余的 DOM 操作(浏览器重排/重绘),严重

影响性能。批处理通过收集短时间内的多个状态更新,合并为一次状态计算和一次渲染,从而减少 DOM 操作,提升应用性能。

示例(未批处理 vs 批处理):

Code block

1 2// 多次状态更新

3setState({ count: 1 });

4setState({ name: 'xxx' });

5setState({ isShow: true });

  • 未批处理:触发 3 次渲染,3 次虚拟 DOM 对比,3 次 DOM 更新;

• 批处理:触发 1 次渲染,1 次虚拟 DOM 对比,1 次 DOM 更新(合并 3 个状态更新为一个完整状

态)。

2. 旧版 React 的批处理局限(React17 及之前)

React17 及之前的批处理机制存在「场景限制」,仅在 React 自身控制的执行环境中支持批处理,在非 React 控制的环境中不支持,导致部分场景下仍会出现冗余渲染:

(1)支持批处理的场景

  • React 合成事件回调(如 onClick、onChange、onSubmit 等);
  • React 生命周期方法(如 componentDidMount、componentDidUpdate 等);
  • React Hooks 回调(如 useEffect 等)。

(2)不支持批处理的场景

  • 原生 DOM 事件回调(如 addEventListener 绑定的事件);
  • 定时器回调(如 setTimeout、setInterval);
  • Promise 回调(如 Promise.then、async/await 后续逻辑);
  • 手动调用的同步代码块。

4const [name, setName] = useState('');

5 6useEffect(() => {

7// setTimeout中不支持批处理,触发2次渲染
8setTimeout(() => {
9setCount(1);
10setName('xxx');
11}, 0);
12}, []);

13

14console.log('组件渲染'); //输出2次
15return <div>{count} - {name}</div>;
16}

3. 自动批处理(Automatic Batching)的优化:突破场景限制

React 18 引入的自动批处理,核心优化是「将批处理的范围扩展到所有场景」,无论状态更新发生在 React 控制的环境还是非 React 控制的环境,默认都进行批处理,从而彻底解决旧版的冗余渲染问

题。

(1)自动批处理支持的场景(全覆盖)

  • 保留旧版支持的场景(合成事件、生命周期、Hooks 回调);
  • 新增支持场景:原生事件、定时器、Promise 回调、async/await 等所有异步/同步场景。

示例(React18 中自动批处理):

Code block

1 2function App() {

3const [count, setCount] = useState(0);

4const [name, setName] = useState('');

5 6useEffect(() => {

7// setTimeout中自动批处理,仅触发1次渲染
8setTimeout(() => {
9setCount(1);
10setName('xxx');
11}, 0);
12}, []);

(2)如何启用自动批处理?

自动批处理默认启用,但需使用 React18 新增的根节点渲染 API(createRoot):

Code block

1 2// 启用自动批处理(推荐)

3const root = ReactDOM.createRoot(document.getElementById('root'));

4root.render(<App />);

5 6// 旧版 render API(不启用自动批处理,兼容旧代码)

7ReactDOM.render(<App />, document.getElementById('root'));

(3)特殊需求:强制同步更新

若需在某些场景下避免批处理(强制同步更新),可使用 ReactDOM.flushSync 包裹状态更新:

Code block

1 2import { flushSync } from 'react-dom';

3 4setTimeout(() => {

5flushSync(() => {

6setCount(1); //强制同步更新,触发1次渲染
7});
8setName('xxx'); //单独触发1次渲染
9 }, 0);
  1. 自动批处理如何改善性能?

自动批处理通过以下两个核心方式提升 React 应用性能:

•(1)减少渲染次数:将分散在不同场景的多个状态更新合并为一次渲染,避免了旧版非 React 控

制场景下的多次冗余渲染,减少了虚拟 DOM 对比和真实 DOM 更新的次数;

•(2)降低主线程开销:真实 DOM 操作(重排/重绘)是浏览器主线程的高开销任务,自动批处理

减少了 DOM 操作次数,降低了主线程的负担,避免了因频繁渲染导致的页面卡顿,尤其在复杂组件树和频繁状态更新场景下(如列表筛选、表单联动)效果显著。

总结:自动批处理是 React18 对批处理机制的“全场景升级”,无需开发者手动优化,即可默认获得

全站分卷索引 · 28 卷
  1. 1第 1 卷
  2. 2第 2 卷
  3. 3第 3 卷
  4. 4第 4 卷
  5. 5第 5 卷
  6. 6第 6 卷
  7. 7第 7 卷
  8. 8第 8 卷
  9. 9第 9 卷
  10. 10第 10 卷
  11. 11第 11 卷
  12. 12第 12 卷
  13. 13第 13 卷
  14. 14第 14 卷
  15. 15第 15 卷
  16. 16第 16 卷
  17. 17第 17 卷
  18. 18第 18 卷
  19. 19第 19 卷
  20. 20第 20 卷
  21. 21第 21 卷
  22. 22第 22 卷
  23. 23第 23 卷
  24. 24第 24 卷
  25. 25第 25 卷
  26. 26第 26 卷
  27. 27第 27 卷
  28. 28第 28 卷