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()
,這可能需要您的 bundler 或框架支援。使用此模式需要您導入的延遲載入元件被導出為 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() {
// ...
}