flushSync

陷阱

使用 flushSync 并不常见,并且可能会损害应用程序的性能。

flushSync 允许你强制 React 同步刷新提供的回调函数内的任何更新。 这确保了 DOM 立即更新。

flushSync(callback)

参考

flushSync(callback)

调用 flushSync 强制 React 刷新任何挂起的任务并同步更新 DOM。

import { flushSync } from 'react-dom';

flushSync(() => {
setSomething(123);
});

大多数情况下,可以避免使用 flushSync。 将 flushSync 作为最后的手段。

请参阅下面的更多示例。

参数

  • callback:一个函数。 React 会立即调用此回调函数,并同步刷新它包含的任何更新。 它也可能刷新任何挂起的更新、Effect 或 Effect 内部的更新。 如果更新因这次 flushSync 调用而挂起,则回退组件可能会重新显示。

返回值

flushSync 返回 undefined

注意事项

  • flushSync 可能会严重损害性能。 请谨慎使用。
  • flushSync 可能会强制挂起的 Suspense 边界显示其 fallback 状态。
  • flushSync 可能会运行挂起的 Effect,并在返回之前同步应用它们包含的任何更新。
  • flushSync 可能会在必要时刷新回调函数外部的更新,以便刷新回调函数内部的更新。 例如,如果有来自点击的挂起更新,React 可能会在刷新回调函数内部的更新之前刷新这些更新。

用法

刷新第三方集成的更新

在与第三方代码(如浏览器 API 或 UI 库)集成时,可能需要强制 React 刷新更新。使用 flushSync 可以强制 React 在回调中同步刷新任何状态更新

flushSync(() => {
setSomething(123);
});
// By this line, the DOM is updated.

这确保了在下一行代码运行时,React 已经更新了 DOM。

使用 flushSync 并不常见,并且频繁使用它会严重损害应用程序的性能。如果你的应用程序只使用 React API,并且没有与第三方库集成,那么 flushSync 应该是没有必要的。

但是,它可以帮助与第三方代码(如浏览器 API)集成。

一些浏览器 API 希望在回调结束时将结果同步写入 DOM,以便浏览器可以使用渲染后的 DOM 进行操作。在大多数情况下,React 会自动为你处理这个问题。但在某些情况下,可能需要强制进行同步更新。

例如,浏览器 onbeforeprint API 允许你在打印对话框打开之前立即更改页面。这对于应用自定义打印样式非常有用,可以让文档在打印时显示得更好。在下面的例子中,你在 onbeforeprint 回调中使用 flushSync 立即将 React 状态“刷新”到 DOM。然后,当打印对话框打开时,isPrinting 将显示为“yes”。

import { useState, useEffect } from 'react';
import { flushSync } from 'react-dom';

export default function PrintApp() {
  const [isPrinting, setIsPrinting] = useState(false);

  useEffect(() => {
    function handleBeforePrint() {
      flushSync(() => {
        setIsPrinting(true);
      })
    }

    function handleAfterPrint() {
      setIsPrinting(false);
    }

    window.addEventListener('beforeprint', handleBeforePrint);
    window.addEventListener('afterprint', handleAfterPrint);
    return () => {
      window.removeEventListener('beforeprint', handleBeforePrint);
      window.removeEventListener('afterprint', handleAfterPrint);
    }
  }, []);

  return (
    <>
      <h1>isPrinting: {isPrinting ? 'yes' : 'no'}</h1>
      <button onClick={() => window.print()}>
        Print
      </button>
    </>
  );
}

如果不使用 flushSync,打印对话框将显示 isPrinting 为“no”。这是因为 React 异步批处理更新,并且在状态更新之前就显示了打印对话框。

陷阱

flushSync 会严重影响性能,并可能意外地强制挂起的 Suspense 边界显示其 fallback 状态。

大多数情况下,可以避免使用 flushSync,因此请将 flushSync 作为最后的手段。