lazy 用于延迟加载组件代码,直到组件第一次渲染。

const SomeComponent = lazy(load)

参考

lazy(load)

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

import { lazy } from 'react';

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

请参见下面的更多示例。

参数

  • load:一个返回 Promise 或其他可执行 then 方法的对象(类似 Promise 的对象,具有 then 方法)的函数。只有在你第一次尝试渲染返回的组件时,React 才会调用 load。React 第一次调用 load 后,它将等待其解析,然后将解析值中的 .default 作为 React 组件进行渲染。返回的 Promise 和 Promise 的解析值都会被缓存,因此 React 不会多次调用 load。如果 Promise 拒绝,React 将 抛出拒绝原因,以便最近的错误边界进行处理。

返回值

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


load 函数

参数

load 函数不接收任何参数。

返回值

你需要返回一个 Promise 或其他可执行 then 方法的类似 Promise 对象(类似 Promise 的对象)。它最终需要解析为一个对象,该对象的 .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() {
// ...
}