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* オブジェクト(`then` メソッドを持つ 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` はキャッシュされるため、読み込み状態は表示されません。読み込み状態を再度表示するには、サンドボックスの「リセット」をクリックしてください。
Suspense を使用した読み込み状態の管理の詳細については、こちらをご覧ください。
トラブルシューティング
遅延読み込みコンポーネントの状態が予期せずリセットされます
他のコンポーネントの*内部*で遅延読み込みコンポーネントを宣言しないでください。
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() {
// ...
}