לפני שהקומפוננטות שלכם מוצגות על המסך, הם חייבים לעבור רינדור על ידי React. הבנת שלבי תרופות זה תעזור לכם איך הקוד שלכם רץ ולהסביר את ההתנהגות שלו.

You will learn

  • מה השפעה של רינדור ב-React
  • מתי ולמה תגובה מרנדרת קומפוננטה
  • מהם השלבים שכוללים הצגה של קומפוננטה על המסך
  • למה רינדור לא תמיד מייצר עדכון DOM

דמיינו שהקומפוננטות שלכם טבחים במטבח שהן מהן מנות טעימות מהן. בתרחיש הזה, React הוא המלצר שמקבל הזמנות מהלקוחות ומביא להם את המנות. בקשה של בקשה והגשה של UI כולל שלושה שלבים:

  1. הפעלה (הפעלה) רינדור (העברת הזמנת הלקוח למטבח)
  2. רינדור (עיבוד) הקומפוננטה (הכנת ההזמנה במטבח)
  3. ביצוע Commit L-DOM (Committing) (הנחת ההזמנה על השולחן)
  1. React בתור מלצר במסעדה: לוקח הזמנות מהמשתמשים ומעביר אותן למטבח הקומפוננטות.
    טריגר
  2. השף של כרטיס (Card) נותן ל-React קומפוננטת Card חדשה.
    רינדור
  3. React מגישה את כרטיס ה-Card למשתמש בשולחן.
    קומיט

Illustrated by Rachel Lee Nabors

שלב 1: טריגר לרינדור

יש שתי סיבות לרינדור של קומפוננטה:

  1. זהו הרינדור הראשוני של הקומפוננטה.
  2. ה-מצב של הקומפוננטה (או של אחד מהאבות שלה) עודכן.

רינדור ראשוני

כשהאפליקציה מתחילה, צריך להפעיל את הרינדור הראשוני. מסגרות ו-sandboxes לפעמים מסתירים את הקוד הזה, אבל הוא מתקדם על ידי קריאה ל-createRoot עם צומת DOM יעד, ואז קריאה קודמת שלו עם הקומפוננטה שלכם:

import Image from './Image.js';
import { createRoot } from 'react-dom/client';

const root = createRoot(document.getElementById('root'))
root.render(<Image />);

נסו להעיר את הקריאה ל-root.render() ותראו את הקומפוננטה נעלמת!

רינדורים חוזרים כש-state מתעדכן

לאחר שהקומפוננטה רונדרה לראשונה, אפשר להפעיל רינדורים נוספים על ידי עדכון מצב עם פונקציית set. עדכון ה-state של הקומפוננטה מכניס רינדור לתור אוטומטי אוטומטי. (אפשר להדמיין זאת כאורח במסעדה שמזמין תה, קינוח ועוד דברים אחרי ההזמנה הראשונה, לפי רמת הצמא או הרעב שלו.)

  1. React כמלצר במסעדה מגיש למשתמש ממשק Card. המשתמש מבקש כרטיס ורוד במקום שחור.
    עדכון state...
  2. React חוזרת למטבח הקומפוננטות ואומרת לשף של Card שצריך כרטיס ורוד.
    ...מפעיל...
  3. שף ה-Card נותן ל-React את הכרטיס הוורוד.
    ...רינדור!

Illustrated by Rachel Lee Nabors

שלב 2: תגובה מרנדרת את הקומפוננטות שלכם

אחרי שהפעלתם רינדור, הגיבו קוראת לקומפוננטות שלכם כדי להבין מה להציג על המסך. “עיבוד” הוא תגובה שקוראת לקומפוננטות שלכם.

  • ברינדור הראשוני, React תקרא לקומפוננת השורש.
  • ברינדורים הבאים, תגובה תקרא לקומפוננטת הפונקציה שעדכון ה-state שלה הפעיל את הרינדור.

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

בדוגמה הבאה, React תקרא ל-Gallery() ול-Image() כמה פעמים:

export default function Gallery() {
  return (
    <section>
      <h1>Inspiring Sculptures</h1>
      <Image />
      <Image />
      <Image />
    </section>
  );
}

function Image() {
  return (
    <img
      src="https://i.imgur.com/ZF6s192.jpg"
      alt="'Floralis Genérica' by Eduardo Catalano: a gigantic metallic flower sculpture with reflective petals"
    />
  );
}

  • ברינדור הראשוני, React תיצור את DOM nodes עבור <section>, <h1>, ושלוש תגיות <img>.
  • בריינדור חוזר, React תחשב אילו מאפיינים (אם בכלל) השתנו מאז הרינדור הקודם. היא לא תעשה עם זה דבר עד לשלב הבא, שלב ה-commit.

Pitfall

עיבוד חייב תמיד להיות חישוב טהור:

  • אותם קלטים, אותו פלט. בהינתן אותם קלטים, קומפוננטה צריכה תמיד להחזיר אותו JSX. (אם מישהו יזמין סלט עם עגבניות, הוא לא אמור לקבל סלט עם בצל!)
  • היא מתעסקת בעניינים שלה. היא לא צריכה לשנות אובייקטים או משתנים שהיו קיימים לפני הרינדור. (הזמנה אחת לא אמורה לשנות את ההזמנה של מישהו אחר.)

אחרת, אתם צריכים להיתקל בבאגים מבלבלים ובהתנהגות לא צפויה ככל הקוד שאתם גדלים ומסתבך. בפיתוח ב-”Strict Mode”, תגובה קוראת לפונקציה של כל קומפוננטה פעמיים, מה שיכול לעזור לחשוף טעויות שנובעות מפונקציות לא טהורות.

Deep Dive

אופטימיזציית ביצועים

התנהגות ברירת המחדל של רינדור. אם אתם נתקלים בבעיית ביצועים, יש כמה דרכים אופציונליות לפתור כפי אותה שמתואר בחלק Performance. אל תבצעו אופטימיזציה מוקדם מדי!

שלב 3: React מבצעת commit לשינויים ב-DOM

אחרי רינדור (קריאה) של הקומפוננטות, תגיב תשנה את ה-DOM.

  • בריינדור הראשוני, React תשתמש ב-API של DOM בשם appendChild() כדי לשים על המסך את כל ה-DOM nodes שיצרה.
  • ברינדורים חוזרים, React תחיל את הפעולות המינימליות בזמן (שחושבו הרינדור!) כדי ל-DOM להתאים להתאים הרינדור העדכני.

הגיב משנה DOM צמתי רק אם יש הבדל בין רינדורים. לדוגמה, הנה קומפוננטה שמרונדרת מחדש עם props שונים שמועברים מההורה כל השניה. שימו לב שאפשר לאפשר טקסט בתוך <input>, ולעדכן את ה-value שלו, אבל הטקסט לא נעלם כשהקומפוננטה מרונדרת מחדש:

export default function Clock({ time }) {
  return (
    <>
      <h1>{time}</h1>
      <input />
    </>
  );
}

זה עובד כי זה האחרון הזה תגובה מעדכנת רק את התוכן של <h1> עם זמן החדש. היא רואה ש-<input>`` מופיעה ב-JSX באותו מקום כמו פעם הקודמת, אז תגיב לא נוגעת ב-``<input>`` — או ב-value` שלו!

אפילוג: צביעת הדפדפן

אחרי שהרינדור הסתיים ו-React עדכנה את ה-DOM, הדפדפן יצבע מחדש את המסך. למרות שהתהליך הזה מוכר כ-”עיבוד דפדפן”, אנחנו קוראים לו “ציור” כדי למנוע בלבול בתיעוד.

דפדפן שמבצע צביעה מחדש של המסך לאחר עדכון DOM.

Illustrated by Rachel Lee Nabors

Recap

  • כל עדכון מסך באפליקציית תגובה מתרחשת בשלושה שלבים:
    1. טריגר (טריגר)
    2. רנדר (רינדור)
    3. Commit (קומיט)
  • אפשר להשתמש ב-Strict Mode כדי למצוא טעויות בקומפוננטות
  • תגיב לא נוגעת ב-DOM אם תוצאת הרינדור זה לפעם הקודמת