lazy
允许你推迟加载组件的代码,直到它第一次渲染。
¥lazy
lets you defer loading component’s code until it is rendered for the first time.
const SomeComponent = lazy(load)
参考
¥Reference
lazy(load)
在组件外部调用 lazy
以声明延迟加载的 React 组件:
¥Call lazy
outside your components to declare a lazy-loaded React component:
import { lazy } from 'react';
const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));
参数
¥Parameters
-
load
:一个函数,返回 Promise 或另一个 thenable(具有then
方法的类似 Promise 的对象)。在你第一次尝试渲染返回的组件之前,React 不会调用load
。React 首先调用load
后,会等待它解析,然后将解析值的.default
渲染为 React 组件。返回的 Promise 和 Promise 的解析值都会被缓存,所以 React 不会多次调用load
。如果 Promise 拒绝,React 将throw
拒绝原因到最近的错误边界来处理。¥
load
: A function that returns a Promise or another thenable (a Promise-like object with athen
method). React will not callload
until the first time you attempt to render the returned component. After React first callsload
, it will wait for it to resolve, and then render the resolved value’s.default
as a React component. Both the returned Promise and the Promise’s resolved value will be cached, so React will not callload
more than once. If the Promise rejects, React willthrow
the rejection reason for the nearest Error Boundary to handle.
返回
¥Returns
lazy
返回一个可以在树中渲染的 React 组件。当惰性组件的代码仍在加载时,尝试渲染它将会挂起。使用 <Suspense>
在加载时显示加载指示器。
¥lazy
returns a React component you can render in your tree. While the code for the lazy component is still loading, attempting to render it will suspend. Use <Suspense>
to display a loading indicator while it’s loading.
load
函数
¥load
function
参数
¥Parameters
load
没有参数。
¥load
receives no parameters.
返回
¥Returns
你需要返回一个 Promise 或其他一些 thenable(具有 then
方法的类似 Promise 的对象)。它最终需要解析为 .default
属性是有效 React 组件类型的对象,例如函数、memo
或 forwardRef
组件。
¥You need to return a Promise or some other thenable (a Promise-like object with a then
method). It needs to eventually resolve to an object whose .default
property is a valid React component type, such as a function, memo
, or a forwardRef
component.
用法
¥Usage
使用 Suspense 延迟加载组件
¥Lazy-loading components with Suspense
通常,你使用静态 import
声明导入组件:
¥Usually, you import components with the static import
declaration:
import MarkdownPreview from './MarkdownPreview.js';
要推迟加载此组件的代码,直到它第一次渲染,请将此导入替换为:
¥To defer loading this component’s code until it’s rendered for the first time, replace this import with:
import { lazy } from 'react';
const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));
此代码依赖于 动态 import()
,它可能需要你的打包器或框架的支持。使用此模式要求将你导入的惰性组件导出为 default
导出。
¥This code relies on dynamic import()
, which might require support from your bundler or framework. Using this pattern requires that the lazy component you’re importing was exported as the default
export.
现在你的组件代码已按需加载,你还需要指定加载时应显示的内容。你可以通过将惰性组件或其任何父级封装到 <Suspense>
边界中来做到这一点:
¥Now that your component’s code loads on demand, you also need to specify what should be displayed while it is loading. You can do this by wrapping the lazy component or any of its parents into a <Suspense>
boundary:
<Suspense fallback={<Loading />}>
<h2>Preview</h2>
<MarkdownPreview />
</Suspense>
在此示例中,直到你尝试渲染 MarkdownPreview
的代码时才会加载它。如果 MarkdownPreview
尚未加载,Loading
将显示在其位置。尝试勾选复选框:
¥In this example, the code for MarkdownPreview
won’t be loaded until you attempt to render it. If MarkdownPreview
hasn’t loaded yet, Loading
will be shown in its place. Try ticking the checkbox:
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
将被缓存,因此不会有加载状态。要再次查看加载状态,请单击沙盒上的 “重置”。
¥This demo loads with an artificial delay. The next time you untick and tick the checkbox, Preview
will be cached, so there will be no loading state. To see the loading state again, click “Reset” on the sandbox.
¥Learn more about managing loading states with Suspense.
故障排除
¥Troubleshooting
我的 lazy
组件的状态意外重置
¥My lazy
component’s state gets reset unexpectedly
不要在其他组件中声明 lazy
组件:
¥Do not declare lazy
components inside other components:
import { lazy } from 'react';
function Editor() {
// 🔴 Bad: This will cause all state to be reset on re-renders
const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));
// ...
}
而是,始终在模块的顶层声明它们:
¥Instead, always declare them at the top level of your module:
import { lazy } from 'react';
// ✅ Good: Declare lazy components outside of your components
const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));
function Editor() {
// ...
}