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 元件類型,例如函式、memoforwardRef 元件。


用法

使用 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 將會被快取,因此不會出現載入狀態。要再次看到載入狀態,請點擊沙盒上的「重設」。

進一步了解如何使用 Suspense 管理載入狀態。


疑難排解 ...

我的 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() {
// ...
}