陷阱

使用 flushSync 并不常见,并且会影响应用的性能。

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

flushSync(callback)

参考

flushSync(callback)

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

import { flushSync } from 'react-dom';

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

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

参见下面的更多示例。

参数

  • callback:一个函数。React 将立即调用此回调函数并同步刷新其中包含的任何更新。它还可以刷新任何挂起的更新、Effects 或 Effects 内部的更新。如果由于此 flushSync 调用导致更新挂起,则可能会重新显示回退。

返回值

flushSync 返回 undefined

警告

  • flushSync 会显著降低性能。谨慎使用。
  • flushSync 可能会强制挂起的 Suspense 边界显示其 fallback 状态。
  • flushSync 可能会运行挂起的 Effects 并同步应用其中包含的任何更新,然后再返回。
  • 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 边界显示其回退状态。

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