正如中所解释的这个问题 https://stackoverflow.com/a/54496445/1804173,React 在 React 事件处理程序中批处理状态更新调用。
如果状态更新是从基于 React 的事件(例如按钮单击或输入更改)中触发的,React 当前将批量状态更新。如果更新是在 React 事件处理程序之外触发的,例如异步调用,它不会批量更新。
I.e., a setFoo
and setBar
当从 React 事件处理程序回调中调用时,将融合在一起。
我正在处理各种第三方库,其中一些包装非 React JS 库。我正在向它们传递回调,我想知道这些回调是否属于“React 事件处理程序”类别,即状态更新批处理是否适用于它们。
有没有办法手动检查状态更新是否是批量的,或者等效地,是否在 React 事件处理程序中执行某些代码?我正在考虑进行临时检查,例如:
let callback = () => {
// fictitious checks
console.log(ReactDOM.checkIfUpdatesAreBatched());
console.log(ReactDOM.checkIfRunningInReactEventHandler());
setFoo("foo");
setBar("bar");
}
Edit: 我不想知道这个的原因是为了确保Foo
and Bar
出于一致性原因,更新是原子的。当然,我可以将状态融合在一起,但这会带来性能问题,因为setFooAndBar
触发太多组件重新渲染,这当然可以通过进一步记忆来缓解......如果我能证明这一点setFoo
and setBar
始终使用更新批处理运行状态分离是合理的。
有没有办法手动检查状态更新是否是批量的,或者等效地,是否在 React 事件处理程序中执行某些代码?
只需登录render
function(函数组件体),当批处理发生时,你将得到一个日志而不是两个。
确保只有此事件会导致重新渲染。
请注意,即使在非 React 事件中,批处理的常见解决方法是将状态移动到单个对象中。您还可以使用另一个useEffect
并从中导出其他状态。
完整示例:
function Component() {
const [a, setA] = useState("a");
const [b, setB] = useState("b");
console.log({ a });
console.log({ b });
const onClick = () => {
setA("aa");
setB("bb");
};
const onClickPromise = () => {
Promise.resolve().then(() => {
setA("aa");
setB("bb");
});
};
const [batch, setBatch] = useState({ a, b });
const onClickPromiseBatched = () => {
Promise.resolve().then(() => {
setBatch({ a: "aa", b: "bb" });
});
};
useEffect(() => {
// Will get another render for deriving the state
// Or just use only the batched state
setA(batch.a);
setB(batch.b);
}, [batch]);
return (
<>
<button onClick={onClick}>Render</button>
<button onClick={onClickPromise}>Render with promise</button>
<button onClick={onClickPromiseBatched}>
Render with promise batched
</button>
</>
);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)