【React】理解学习 React 17中的批处理 与 18 批处理
最近在看 React 18 时,发现 18 已经默认将你的状态更新进行批处理了,不需要再像 16、17 内使用
unstable_batchedUpdates
这种 Hack Api 了~
什么是批处理?
批处理是将多个状态更新分组到单个 re-render 内,以获得更好的性能操作。
比如在同一个点击事件内更新两个 state,React 将会把它们分到一个 render 内重新渲染,看下方 demo 内的 console 可体现。
在多个状态更新的时候,批处理可以避免不必要的重新渲染。然而在旧版本内何时批处理也并不完全一致,比如在
click
内去请求数据后再更新 state,此时 react 则不会批量更新,而是进行两次独立的更新
17 Batch Demo: 不批处理外部事件处理程序(注意 render 次数)
在 React 18 之前,React 只在事件处理程序期间批量更新。默认情况下,React 不会对 Promise、setTimeout、原生事件处理程序(native event handlers)或其他的React默认不进行批处理的事件进行批处理操作。
自动批处理
从 React 18 的
creatRoot
开始,所有的更新都将自动批处理,无论它们来自何处。这意味着 timeouts, promises, native event handlers,或者任何其他事件内的更新都将以 React 事件内的更新相同的方式进行批处理。我们希望这会减少渲染,获得更好的性能。
注意!React 18 仍可使用
render
(旧行为render
的存在只是为了跟容易对两个版本进行生产实验),且保留旧行为,与全新的 createRoot 存在差异!
如何不进行批处理
通常,批处理是安全的,但某些代码可能依赖于在状态更改后立即从 Dom 中读取某些内容。对于这些用例,可以使用
React.flushSync()
退出批处理
import { flushSync } from 'react-dom'; // Note: react-dom, not react
function handleClick() {
flushSync(() => {
setCounter(c => c + 1);
});
// React has updated the DOM by now
flushSync(() => {
setFlag(f => !f);
});
// React has updated the DOM by now
}
与
unstable_batchedUpdates
相同的是flushSync
内的更新也是批量,所以不要批处理的话需要考虑下逻辑的正确性