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 组件类型,例如函数、memo
或 forwardRef
组件。
用法
使用 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
将被缓存,因此不会出现加载状态。要再次查看加载状态,请单击沙盒上的“重置”。
故障排除
我的 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() {
// ...
}