lazy מאפשרת לדחות טעינה של קוד קומפוננטה עד לרינדור הראשון שלה.

const SomeComponent = lazy(load)

הפניה

lazy(load)

קראו ל-lazy מחוץ לקומפוננטות שלכם כדי להצהיר על קומפונטת React בטעינה עצלה:

import { lazy } from 'react';

const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));

עוד דוגמאות נוספות.

פרמטרים

  • load: פונקציה שמחזירה הבטחה או thenable אחר פונקציה אישית דמוית הבטחה עם מתודת then). React לא תקרא ל-load עד הפעם הראשונה שבה תנסו לרנדר היא את הקומפוננטה המוחזרת. תיפתר, ואז תרנדר את .default של הערך כקומפוננטת React גם ה-Promise המוחזר וגם הערך שנפתר ממנו ישמרו במטמון, כך ש-React לא תקרא ל-load יותר מ-TK_5__ יותר מ-TK_5__ יותר מ-TK_5__ יותר מה-TK___12 הבטחה אחת. שגיאה Boundary בקרוב כדי שיטפל בה.

מחזירה

lazy מחזירה קומפונטת React אפשר לרנדר בעץ שלכם. בזמן שקוד הקומפוננטה העצלה עדיין נטען, ניסיון לרנדר אותה יגרום ל-השעיה. השתמשו ב-<Suspense> כדי להציג אינדיקציית טעינה בזמן שהיא נטענת.


פונקציית load

פרמטרים

load לא מקבלת פרמטרים.

מחזירה

צריך להחזיר הבטחה או thenable אחר (אובייקט דמוי הבטחה עם מתודת then). בסופו של דבר היא צריכה להיפתר לאובייקט שהמאפיין .default שלו הוא סוג קומפוננטת React תקין, כמו פונקציה, קומפונטת [//TK_2__]Kreference. קומפונטת forwardRef.


שימוש

טעינת קומפונטות בעצלות עם Suspense

בדרך כלל מייבאים קומפונטות באמצעות הצהרת import סטטיסטית:

import MarkdownPreview from './MarkdownPreview.js';

כדי לדחות טעינה של קוד הקומפוננטה הזו עד לרינדור הראשון שלה, החליפו את הייבוא הזה ב:

import { lazy } from 'react';

const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));

הקוד נשען על import() דינמי, שעשוי לדרוש תמיכה מה-bundler או מה-framework שלכם. שימוש בדפוס הזה דורש שהקומפוננטה העצמה שהם מייבאים יוצאים כ-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 כבר תהיה במטמון, לא תהיה מצב טעינה. כדי לראות שוב את מצב הטעינה, לחצו על “איפוס” ב-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() {
// ...
}