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 组件类型,例如函数、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() {
// ...
}