lazy 允许您推迟加载组件的代码,直到它第一次被渲染。

const SomeComponent = lazy(load)

参考

lazy(load)

在组件外部调用 lazy 来声明一个延迟加载的 React 组件

import { lazy } from 'react';

const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));

请参阅下面的更多示例。

参数

  • load:一个返回 Promise 或其他 *thenable*(具有 then 方法的类 Promise 对象)的函数。在您第一次尝试渲染返回的组件之前,React 不会调用 load。在 React 首次调用 load 之后,它会等待它解析,然后将解析值的 .default 渲染为 React 组件。返回的 Promise 和 Promise 的解析值都将被缓存,因此 React 不会多次调用 load。如果 Promise 被拒绝,React 将 throw 拒绝原因以供最近的错误边界处理。

返回值

lazy 返回一个您可以在树中渲染的 React 组件。当延迟加载组件的代码仍在加载时,尝试渲染它将 *暂停。* 使用 <Suspense> 在加载时显示加载指示器。


load 函数

参数

load 不接收任何参数。

返回值

您需要返回一个 Promise 或其他 可 thenable 对象(一个类似 Promise 的对象,具有 then 方法)。它需要最终解析为一个对象,其 .default 属性是一个有效的 React 组件类型,例如函数、memoforwardRef 组件。


用法

使用 Suspense 延迟加载组件

通常,您使用静态 import 声明导入组件

import MarkdownPreview from './MarkdownPreview.js';

要推迟加载此组件的代码,直到它第一次被渲染,请将此导入替换为

import { lazy } from 'react';

const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));

此代码依赖于 动态 import(),这可能需要您的打包器或框架的支持。使用此模式要求您正在导入的延迟加载组件被导出为 default 导出。

现在您的组件代码是按需加载的,您还需要指定在加载时应该显示什么。您可以通过将延迟加载组件或其任何父组件包装到 <Suspense> 边界中来实现

<Suspense fallback={<Loading />}>
<h2>Preview</h2>
<MarkdownPreview />
</Suspense>

在此示例中,只有在您尝试渲染 MarkdownPreview 时才会加载其代码。如果 MarkdownPreview 尚未加载,则会显示 Loading 来代替它。尝试勾选复选框

import { useState, Suspense, lazy } from 'react';
import Loading from './Loading.js';

const MarkdownPreview = lazy(() => delayForDemo(import('./MarkdownPreview.js')));

export default function MarkdownEditor() {
  const [showPreview, setShowPreview] = useState(false);
  const [markdown, setMarkdown] = useState('Hello, **world**!');
  return (
    <>
      <textarea value={markdown} onChange={e => setMarkdown(e.target.value)} />
      <label>
        <input type="checkbox" checked={showPreview} onChange={e => setShowPreview(e.target.checked)} />
        Show preview
      </label>
      <hr />
      {showPreview && (
        <Suspense fallback={<Loading />}>
          <h2>Preview</h2>
          <MarkdownPreview markdown={markdown} />
        </Suspense>
      )}
    </>
  );
}

// Add a fixed delay so you can see the loading state
function delayForDemo(promise) {
  return new Promise(resolve => {
    setTimeout(resolve, 2000);
  }).then(() => promise);
}

此演示加载时会有人为延迟。下次您取消勾选并勾选复选框时,Preview 将被缓存,因此不会出现加载状态。要再次查看加载状态,请单击沙盒上的“重置”。

详细了解如何使用 Suspense 管理加载状态。


故障排除

我的 lazy 组件的状态意外重置

不要在其他组件内部声明 lazy 组件

import { lazy } from 'react';

function Editor() {
// 🔴 Bad: This will cause all state to be reset on re-renders
const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));
// ...
}

而应始终在模块的顶层声明它们

import { lazy } from 'react';

// ✅ Good: Declare lazy components outside of your components
const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));

function Editor() {
// ...
}