lazy מאפשרת לדחות טעינה של קוד קומפוננטה עד לרינדור הראשון שלה.
const SomeComponent = lazy(load)Reference
lazy(load)
קראו ל-lazy מחוץ לקומפוננטות שלכם כדי להצהיר על קומפוננטת React בטעינה עצלה:
import { lazy } from 'react';
const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));Parameters
load: פונקציה שמחזירה Promise או thenable אחר (אובייקט דמוי Promise עם מתודתthen). React לא תקרא ל-loadעד הפעם הראשונה שבה תנסו לרנדר את הקומפוננטה המוחזרת. אחרי ש-React קוראת ל-loadבפעם הראשונה, היא תחכה שהפונקציה תיפתר, ואז תרנדר את.defaultשל הערך שנפתר כקומפוננטת React. גם ה-Promise המוחזר וגם הערך שנפתר ממנו יישמרו במטמון, כך ש-React לא תקרא ל-loadיותר מפעם אחת. אם ה-Promise נדחה, React תבצעthrowלסיבת הדחייה עבור Error Boundary הקרוב כדי שיטפל בה.
Returns
lazy מחזירה קומפוננטת React שאפשר לרנדר בעץ שלכם. בזמן שקוד הקומפוננטה העצלה עדיין נטען, ניסיון לרנדר אותה יגרום ל-suspend. השתמשו ב-<Suspense> כדי להציג אינדיקציית טעינה בזמן שהיא נטענת.
פונקציית load
Parameters
load לא מקבלת פרמטרים.
Returns
צריך להחזיר 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 או מה-framework שלכם. שימוש בדפוס הזה דורש שהקומפוננטה העצלה שאתם מייבאים יוצאה כ-default export.
עכשיו, כשהקוד של הקומפוננטה נטען לפי דרישה, צריך גם לציין מה יוצג בזמן הטעינה. אפשר לעשות זאת על ידי עטיפת הקומפוננטה העצלה או אחד מההורים שלה בתוך גבול <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 כבר יהיה במטמון, ולכן לא יהיה מצב טעינה. כדי לראות שוב את מצב הטעינה, לחצו על “Reset” ב-sandbox.
קראו עוד על ניהול מצבי טעינה עם Suspense.
פתרון תקלות
ה-state של קומפוננטת 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() {
// ...
}