在 React 18 中,批处理的支持范围得到了扩展,不仅包括 React 自身的事件处理,还包括 Promise、setTimeout 和原生事件处理器等。这意味着在这些情况下,多个状态更新将被批量处理,以减少重新渲染的次数,提高性能。
批处理示例
以下是一个详细的示例,展示了在 React 18 中如何使用批处理来处理多个状态更新。
示例代码
import React, { useState } from 'react';
import ReactDOM from 'react-dom/client';
const App = () => {
const [count, setCount] = useState(0);
const [text, setText] = useState('');
const handleClick = () => {
// 使用 Promise 进行状态更新
Promise.resolve().then(() => {
setCount(c => c + 1);
setText('Updated in Promise');
});
// 使用 setTimeout 进行状态更新
setTimeout(() => {
setCount(c => c + 1);
setText('Updated in setTimeout');
}, 1000);
// 使用原生事件处理器
document.getElementById('nativeButton').addEventListener('click', () => {
setCount(c => c + 1);
setText('Updated in native event handler');
});
};
return (
<div>
<p>Count: {count}</p>
<p>Text: {text}</p>
<button onClick={handleClick}>Update State</button>
<button id="nativeButton">Native Event Handler</button>
</div>
);
};
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
-
状态声明:
count和text是两个状态变量,分别通过useState钩子声明。
-
handleClick函数:- 在
handleClick函数中,我们演示了如何在 Promise、setTimeout 和原生事件处理器中更新状态。
- 在
-
Promise 状态更新:
- 使用
Promise.resolve().then()来模拟异步操作,并在其中进行状态更新。 setCount(c => c + 1)和setText('Updated in Promise')会被批处理,导致一次重新渲染。
- 使用
-
setTimeout 状态更新:
- 使用
setTimeout来延迟执行状态更新。 - 同样,
setCount(c => c + 1)和setText('Updated in setTimeout')会被批处理。
- 使用
-
原生事件处理器:
document.getElementById('nativeButton').addEventListener('click', () => {...})用于添加一个原生事件处理器。- 在原生事件处理器中,状态更新也会被批处理。
-
渲染组件:
- 使用
ReactDOM.createRoot和root.render来渲染App组件。
- 使用
运行结果
点击 Update State 按钮后:
- 立即通过 Promise 更新状态,
count增加 1,text更新为 "Updated in Promise"。 - 一秒后通过
setTimeout更新状态,count再次增加 1,text更新为 "Updated in setTimeout"。 - 点击
Native Event Handler按钮,通过原生事件处理器更新状态,count再次增加 1,text更新为 "Updated in native event handler"。
在这些情况下,React 18 会自动批处理这些状态更新,以减少重新渲染的次数,提高性能。这是 React 18 的一个重要改进,可以显著优化应用的性能和用户体验。
参考文献: 深入理解React18中的批处理react18给我们带来了更强大的自动批处理机制,但是对于批处理本身究竟做了什么,它的影 - 掘金 (juejin.cn)