提问者:小点点

检测状态更新是否在React Hooks中批处理?


如本问题所述,React批处理React事件处理程序中的状态更新调用。

如果从基于React的事件(如按钮单击或输入更改)中触发,React当前将批处理状态更新。如果更新是在React事件处理程序外部触发的(如异步调用),则不会进行批处理。

也就是说,当从React事件处理程序回调调用时,setFoosetBar将融合在一起。

我正在处理各种第三方库,其中一些包非React JS库。我正在传递回调,我想知道这些回调是否属于“反应事件处理程序”类别,即状态更新批处理是否适用于它们。

是否有一种方法可以手动检查状态更新是否是批处理的,或者等效地检查某些代码是否在React事件处理程序中执行?我在考虑一张临时支票,比如:

let callback = () => {
  // fictitious checks
  console.log(ReactDOM.checkIfUpdatesAreBatched());
  console.log(ReactDOM.checkIfRunningInReactEventHandler());
  setFoo("foo");
  setBar("bar");
}

编辑:我不想知道这一点的原因是为了确保FooBar更新出于一致性原因是原子的。当然,我可以将状态融合在一起,但这会带来性能问题,因为setFooAndBar会触发太多要重新渲染的组件,这当然可以通过进一步记忆来缓解。。。如果我能证明setFoosetBar总是与更新批处理一起运行,那么状态分离将是合理的。


共2个答案

匿名用户

是否有一种方法可以手动检查状态更新是否是批处理的,或者等效地检查某些代码是否在React事件处理程序中执行?

只需在渲染函数(函数组件主体)内登录,当批处理发生时,您将获得单个日志而不是两个。

确保只有此事件导致重新渲染。

值得注意的是,即使在非反应事件中,批处理的一个常见解决方法是将状态移动到单个对象中。您还可以使用另一个useffect并从中派生其他状态。

完整示例:

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>
    </>
  );
}

匿名用户

没有办法做到这一点。你也不会真的需要这个。如果您的功能依赖于具有特定值的状态块,请在依赖数组中使用带有适当状态块的use效应,并在给use效应的回调中有条件地检查这些值。

如果您有一个非常特定的用例,实际上不需要批处理(并且您确定您需要选择退出,99.9999999%的人不需要),那么就存在这个用例

ReactDOM.flushSync(() => {
  // this setState won't be batched
  setState(something)
})

这并不严格相关,但React团队的Dan Abermov与用户讨论了关于输入聚焦的批量更新:https://github.com/facebook/react/issues/18402