lazy 允许你延迟加载组件的代码,直到它首次被渲染。
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给最近的错误边界处理。
返回
🌐 Returns
lazy 返回一个可以在你的组件树中渲染的 React 组件。当懒加载组件的代码仍在加载时,尝试渲染它将会 挂起。使用 <Suspense> 可以在加载时显示一个加载指示器。
load 函数
🌐 load function
参数
🌐 Parameters
load 不接收任何参数。
返回
🌐 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.
故障排除
🌐 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() {
// ...
}