מהם היתרונות של ריאקט ואיך מסבירים את ההבדל בין אלמנט לקומפוננטה? אם אתם מתמיינים למשרה שדורשת ידע ב- React, כדאי שתדעו לענות על השאלות האלו, כי יש סיכוי גדול שזה בדיוק מה שישאלו אתכם.
במאמר הזה ריכזתי 25 שאלות נפוצות שישאלו אתכם במהלך ראיון עבודה מקצועי העוסק בריאקט. השתדלתי לכתוב תשובות מעמיקות, מפורטות ומהימנות ככל הניתן ולספק קישורים למקורות ברשת – בעיקר מהדוקומנטציה הרשמית של ריאקט (אבל לא רק) על מנת שתוכלו להמשיך ולהרחיב את הידע שלכם בנושאים המובאים כאן.
*מאמר זה מיועד לבעלי ידע מקדים ב-JS, HTML וריאקט
תוכן עניינים
#1 – מה זה ריאקט?
ריאקט (React) היא ספריית Open Source בשפת JS ליצירת UI (ממשקי משתמש). ספרייה זו משתמשת בגישה של יצירת ממשקי משתמש אינטראקטיביים, מהירים ומורכבים באמצעות קומפוננטות עצמאיות שמנהלות את ה-state של עצמן.
#2 – כיצד ריאקט עובדת?
ריאקט יוצרת DOM וירטואלי. כאשר ה-state משתנה בקומפוננטה, ריאקט מריצה diffing algorithm אשר מזהה מה השתנה ב-DOM הווירטואלי. בשלב השני מתבצע reconciliation בו ה-DOM מעודכן בתוצאות אלגוריתם ה-diffing.
#3 – מה היתרונות של ריאקט?
-ביצועים משופרים באמצעות השימוש ב-Virtual DOM, שהוא יצוג קל משקל ב-JS של ה-DOM האמיתי. כאשר ה-state משתנה, הריאקט מבצעת השוואה בין ה-VDOM החדש לישן והשינוי ב-DOM האמיתי קורה רק ב-nodes שריאקט מזהה שהשתנו בהשוואה של ה-VDOMS ולא משנה את כל ה-DOM (בהמשך המאמר תמצאו פירוט על ה-VDOM).
-ריאקט בנויה כעץ של קומפוננטות שזרימת הדאטה מתבצעת בו בצורה אחידה מלמעלה למטה – מקומפוננטת אב לקומפוננטת בן (Unidirectional Data Flow in React). פעולות (actions) שנעשות ב-View מעדכנות את ה-state ועדכון זה של ה-state גורם לזרימת דאטה חדשה שמשנה את עץ הקומפוננטות ואת ה-View בהתאם. ה-View הוא התוצר של הסטייט והוא יכול להשתנות רק כאשר action קורה, שמשנה את ה-state וחוזר חלילה.
היתרונות של זרימת הדאטה בכיוון אחד:
- גישה כזו נוטה לפחות שגיאות, שכן יש לנו יותר שליטה על הדאטה.
- יותר קל לדבג את זה כיוון שאנו יודעים מה מגיע ומהיכן.
- זה יותר יעיל שכן ספריית ריאקט יודעת מראש מהם הגבולות של כל חלק במערכת.
- ה-state הוא תמיד בבעלות קומפוננטה מסויימת אחת ויכול להשפיע רק עליה עצמה או על קומפוננטות הבת שלה.
- שינוי ה-state לעולם לא ישפיע על האב או על האחים של הקומפוננטה.
- מסיבה זו ה-state לעתים קרובות יועבר לראש עץ הקומפוננטות, על מנת שניתן יהיה לשתף אותו בין קומפוננטות שצריכות גישה אליו.
-השימוש ב-JSX הופך את הקוד לקל לכתיבה ולקריאה. Declarative views הופך את הקוד לצפוי ולקל לדיבוג. כמו כן באמצעות ה-JSX ריאקט מייצרת את ה-VDOM שראינו לעיל את יתרונותיו.
-הקומפוננטות הן רב שימושיות וחוסכות כתיבת קוד. תהליך הפיתוח נעשה קל יותר כאשר אין צורך לכתוב מאפס קומפוננטות דומות, אלא להשתמש באותן קומפוננטות ולהעביר להן props שונים. דבר זה מזרז את תהליך הפיתוח כולו בעשרות מונים.
–תמיכה גדולה של הקהילה כתוצאה מכך שזאת ספריית open source והיא כה פופולרית. בכל בעיה, באג או כל דבר אחר, הקהילה העשירה מבטיחה שעזרה תימצא במהרה.
#4 – מה זה VDOM) Virtual DOM)?
ה-VDOM הוא ייצוג קל משקל של ה-DOM ב-JS. ייצוג זה נשמר בזיכרון על ידי ריאקט ומסונכרן כל העת עם ה-DOM האמיתי. עדכונים ב-VDOM הם מהירים יותר וקלי משקל מאשר שינויים ב-DOM האמיתי.
כאשר ריאקט מוצא הבדלים בין ה-VDOM הנוכחי לקודם, רק אז הוא מבצע את השינויים הנדרשים ב-DOM האמיתי ורק ב-nodes הרלוונטיים. תהליך השינוי הזה נקרא Reconciliation. העקרונות חשובים אשר עומדים בבסיס תהליך זה הם אלגוריתם המעקב אחרי השינויים (Diffing Algorithm) של ריאקט וה-VDOM.
#5 – מה זה JSX?
ראשי תיבות של JavaScript XML. הרחבת סינטקס (syntax extension) ל-JS, שמתארת איך ה-HTML צריך להראות, באמצעות "כתיבת HTML" בתוך JS ושילוב JS בתוך האלמנטים של ה-HTML כביכול.
ה-JSX הוא "Syntactic sugar" למתודה:
הקוד הזה:
יכול להתקמפל לקוד הזה:
#6 – מה ההבדל בין אלמנט לקומפוננטה?
אלמנטים הם אבני הבניין הקטנים ביותר של אפליקציות ריאקט והם בלתי ניתנים לשינוי (immutable). מרגע שהם נוצרים לא ניתן לשנות את הילדים שלהם או את המאפיינים שלהם. בדיוק כמו פריים בסרט – הם מייצגים את ממשק המשתמש בנקודת זמן מסויימת.
הם מתארים מה צריך להיות בממשק המשתמש ומקבילים לאלמנטים של HTML. אלמנטים בריאקט הם אובייקטים המתארים מה יופיע מבחינת ה-nodes של ה-DOM. יצירת אלמנטים של ראקט היא "זולה" יותר מבחינת משאבים, לעומת יצירת אלמנטים ב-DOM עצמו. אלמנטים בריאקט יקראו בשמות עם אות ראשונה קטנה שזהים לשמות התגיות ב-HTML – כגון <div><button> וכו'.
קומפוננטות קרויות באות ראשונה גדולה </ Button> או באות ראשונה גדולה ונקודה, dot notation – לדוגמה: </ Menu.Item>. קומפוננטות הן מקטעי קוד קטנים, רב שימושיים, שמקבלות props כמשתנים ומחזירות אלמנטים שירונדרו בדף. קומפוננטה יכולה להיות קלאס, שבאמצעות מתודת render תחזיר אלמנטים או יכולה להיות פונקציה שמחזירה אלמנטים.
#7 – מה זה פרגמנט?
פרגמנטים בריאקט מאפשרים לקבץ אלמנטים וקומפוננטות בלי להוסיף ל-DOM עוד nodes שאינם נחוצים.
#8 – מה זה props?
פרופס זה קיצור למילה properties. בעצם, הם ארגומנטים המחזיקים מידע שמועברים לקומפננטה מקומפננת האב שלה. הם מגיעים לקומפוננטת הבת כאובייקט המחזיק בדאטה המועברת.
#9 – מה זה key?
בדרך כלל כאשר מייצרים שורה של אלמנטים או קומפוננטות, באמצעות מתודת map אשר רצה על מערך, יש לתת לכל פריט prop בשם key, שצריך להיות ייחודי לכל פריט. ה-key עוזר לריאקט לזהות איזה פריטים התווספו, השתנו או הוסרו. ה-key נותן זהות ייחודית ויציבה לכל פריט ברשימה וכך ריאקט יכול לבצע שינויים בלי הערכות וחישובים מורכבים, אלא רק על ידי התייחסות ל-key הייחודי של כל פריט.
מומלץ לא להשתמש באינדקס של הפריט במערך כ-key אם סדר הפריטים עלול להשתנות. זה עלול להשפיע באופן שלילי על הביצועים ויכול לפגוע ב-state של הקומפוננטה.
במידה ולא נותנים key לפריטים ברשימה, ריאקט יעניק את האינדקס של הפריט במערך באופן אוטומטי.
#10 – מה זה Hooks?
Hooks הם תוספת חדשה שהתווספה בגרסה 16.8 של ריאקט. hooks הם פונקציות אשר מאפשרות לקומפוננטות פונקציונליות להיות בעלות stste ולגשת ל-life cycle features. הם אינם עובדים בקומפוננטות מבוססות קלאסים ובעצם נועדו לאפשר עבודה עם ריאקט ללא קלאסים.
הקונבנציה והבקשה של ריאקט היא שהשם של פונקציות hook יתחיל במילה use. זה מאפשר לריאקט לבדוק באופן אוטומטי אם כל החוקים של hooks נשמרים מאחורי הקלעים, כמו אי שימוש ב-hook בתוך פונקציה אחרת לדוגמה.
ה-hooks העיקריים הם:
- useState
- useEffect
- useContext
- useReducer
- useRef
- useMemo
- useCallback
ניתן גם לחבר פונקציות hooks מותאמות אישית (custom hooks). הן מאפשרות יצירת לוגיקה עצמאית מבוססת state ו-hooks נוספים, שניתן להתמש בה בצורה רב שימושית ברחבי האפליקציה. חשוב לזכור כי כאשר שתי קומפוננטות משתמשות ב-custom hook הן אינן חולקות את ה-state של ה-custom hook, שכן כל שימוש ב-custom hook, כל ה-state וכל ה-effects מבודדים לחלוטין.
#11 – מה זה state?
ה-state מחזיק אינפורמציה שמנוהלת בתוך הקומפוננטה ויכולה להשתנות במהלך חייה של הקומפוננטה. שינוי האינפורמציה ב-state גורר רנדור מחדש של הקומפוננטה.
ה-state הוא פרטי לקומפוננטה ונמצא בשליטתה המלאה. את ה-state ניתן להעביר רק למטה, לקומפוננטות בת, באמצעות props. שינויים ב-state יש לבצע רק באמצעות מתודת set שגם ניתן להעביר לקומפוננטות הבת כ-props.
#12 – מה זה useState?
פונקציית useState היא hook שמאפשר לנהל את ה-state בקומפוננטה פונקציונלית. פונקציה זו מקבלת ערך ראשוני ל-state ומחזירה מערך בעל שני ערכים – ה-state הנוכחי ומתודת set שבאמצעותה ניתן לעדכן את ה-state. במקרים מסויימים ניתן לעדכן את ה-state במתודת ה-set על ידי החלפתו בערך חדש לגמרי אך במקרים בהם יש לעדכן את ה-state בהתבסס על הערך הקודם של ה-state יש להעביר למתודת ה-set פונקציה, בה מעבירים את הערך הקודם של ה-state ומחזירים ממנה את הערך הקודם יחד עם השינויים הנדרשים.
יש לעשות זאת בצורה הזו משום שמתודת ה-set היא אסינכרונית, כלומר ריאקט מרכז את ההוצאה לפועל של השינויים בסטייט מסיבות של ביצועים ושינוי ה-state לא קורה מייד ברגע שמתודת ה-set נקראת. משום כך אין להסתמך על הערך הנוכחי של ה-state בקריאה ל-set, משום שאיננו יכולים לדעת בוודאות מה יהיה הערך באותו הרגע. לכן כאשר מעבירים פונקציה עם הערך הקודם של ה-state כארגומנט, באמצעות מנגנון closure שריאקט מבצעת מובטח שהערך הנכון יועבר.
כאשר הסטייט הראשוני ב-useState כרוך בחישוב מורכב, או פעולה בזבזנית, יש להעביר את הסטייט הראשוני בתוך פונקציה, כך מבטיחים שהפונקציה תרוץ ברנדור הראשוני בלבד ויהיה חיסכון במשאבים.
בהינתן יותר מ-state אחד בקומפוננטה, ניתן להשתמש בכמה useStates לכל state ונמנע מריכוז כל ה-state באובייקט אחד כפי שהיה נהוג בקומפוננטות מבוססות קלאסים.
#13 – למה אסור לעדכן את ה-state ישירות?
עדכון ישיר של ה-state לא יגרום לקומפוננטה להתרנדר מחדש ולשקף את השינויים בממשק המשתמש. על ידי שימוש במתודת ה-set לעדכון ה-state, ריאקט יקבע עדכון ל-state שיתבצע בצורה אה סינכרונית וירנדר מחדש את הקומפוננטה ברגע שהשינוי יצא לפועל.
#14 – מהן מתודות life cycle?
בקומפוננטות מבוססות קלאסים יש 3 מתודות life cycle שניתן לקרוא להן כדי שיקראו באחד משלושת שלבי החיים של הקומפוננטה:
- componentDidMount – תקרא מייד כשהקומפוננטה מתווספת ל-DOM.
- componentDidUpdate – תופעל כשהקומפוננטה מתעדכנת. היא לא תיקרא ברינדור הראשוני.
- componentWillUnmount – תיקרא מייד לפני שהקומפוננטה מוסרת מה-DOM.
בקומפוננטות פונקציונליות מתודות אלה אינן קיימות אך יש להן מקבילה על ידי שימוש ב-hook מסוג useEffect.
כאשר כותבים את ה-hook והארגומנט השני הוא מערך ריק, הדבר מקביל ל-componentDidMount – והקוד בתוך הפונקציה ירוץ רק בעת שהקומפוננטה מתווספת ל-DOM.
כאשר כותבים את ה-hook ומעבירים נתונים בארגומנט השני, במערך, הקוד בתוך הפונקציה ירוץ כאשר הנתונים האלה ישתנו וזה מקביל ל-componentDidUpdate.
כאשר כותבים את ה-hook ובתוך הפונקציה מחזירים פונקציה, היא תיקרא מייד לפני שהקומפוננטה תוסר מה-DOM וזה מקביל ל-componentWillUnmount.
#15 – מהן controlled and uncontrolled components?
ב-controlled component הדאטה של הטופס (form data) מנוהלת על ידי הקומפוננטה באמצעות ה-state. ב-HTML, האלמנטים של הטופס כמו input למשל, מנהלים ה-state של עצמם בהתבסס על הקלט של המשתמש. בריאקט ה-state הוא בלתי ניתן לשינוי וניתן לעדכנו רק באמצעות מתודת set. ב-controlled component ה-state מהווה single source of truth, וכך הקומפוננטה שמרנדרת את הטופס, גם שולטת מה קורה בטופס לאחר שהמשתמש מכניס את הקלט שלו. טופס שהערכים שלו מנוהלים על ידי הקומפוננטה נקרא controlled component.
ב-uncontrolled component הדאטה של הטופס מנוהלת על ידי ה-DOM עצמו. כדי לכתוב uncontrolled component, במקום לכתוב event handler עבור כל שינוי ב-state, ניתן להשתמש ב-ref כדי לקבל את הערך של הטופס מה-DOM.
בנוסף, controlled component היא קומפוננטה שמקבלת הערך הנוכחי שלה דרך props ומיידעת את קומפוננטת האב שלה אודות שינויים בערך המתקבל, באצעות callbacks, כמו onChange. קומפוננטת האב "שולטת" בה באמצעות טיפול ב-callbacks וניהול הסטייט של עצמה והחזרתו הערך החדש בחזרה לקומפוננטת הבן שוב באמצעות ה-props. ניתן גם לקרוא ל-controlled component – קומפוננטה טיפשה (dumb component).
בהתאם לזאת, uncontrolled component, היא קומפוננטה שמאחסנת את ה-state של עצמה בתוכה, ומתממשקת עם ה-DOM באמצעות ref כדי ללמוד אודות הערך הנוכחי שהיא צריכה. זה דומה לדרך בה פועל HTML.
#16 – מה זה קונטקסט (context)?
באפליקציית React טיפוסית, המידע מועבר למטה (מקומפוננטת אב לקומפוננטת ילד) דרך props, אבל עבור מידע שנדרש בהרבה קומפוננטות באפליקציה (כמו לדוגמא העדפות שפה או ערכת נושא של ממשק המשתמש) השימוש ב-props יכול להיות מסורבל ומיותר כאשר מעבירים פרופס מאב לבן, לנכד ולנין. קומפוננטות שלמות שאינן צריכות את המידע מקבלות אותו ללא צורך. דבר זה נקרא props drilling – חלחול props. קונטקסט מספק דרך לשתף מידע כזה בין קומפוננטות בלי להעביר אותו באופן מפורש לכל קומפוננטה. הקונטקסט נועד לשתף מידע שנחשב ״גלובאלי״ לכל הקומפוננטות בעץ, כמו מידע על המשתמש המאומת, ערכת הנושא או השפה המועדפת. בעזרת הקונטקסט, אפשר להמנע מלהעביר את ה-prop דרך רכיבי ביניים. השימוש בקונטקסט נועד בעיקר למצב שבו חלק מהמידע צריך להיות נגיש להרבה קומפוננטות בעומקים שונים.
#17 – כיצד ניתן להעביר data בין קומפוננטות
מאב לבן – באמצעות props.
מבן לאב – באמצעות callbacks.
כדי להעביר דאטה באופן גלובלי ישירות לכל קומפוננטה שהיא בעץ – באמצעות context או ספריות ניהול state חיצוניות כגון Redux או MobX.
#18 – מהם החסרונות של ריאקט?
- דוקומנטציה רשמית לוקה בחסר.
- עקומת למידה רצינית למתחילים.
- השימוש ב-JSX יכול להיות מסובך למתכנתים מתחילים, שכן הוא מערבב בין syntax של HTML ל-syntax של JS.
#19 – כיצד ניתן לשפר ביצועים בריאקט?
- שימוש ב-React.memo – קומפוננטה מסדר גבוה יותר (higher order component) שתעטוף את הקומפוננטה. המשמעות היא שאם הקומפוננטה תרנדר את אותה תוצאה בהינתן אותם ה-props, ריאקט ידלג על רנדור מחדש של הקומפוננטה ויעשה שימוש בגרסה השמורה של הקומפוננטה (memoizing).
- שימוש בפרגמנטים (React.Fragment) כדי להמנע מהוספת nodes לא נחוצים ל-DOM.
- שימוש ב-React.lazy ו-React.Suspense – טכניקה זו תטען את הקומפוננטה רק כאשר היא תצטרך להיטען.
React Suspense היא קומפוננטה שמשהה את הרינדור של קומפננטה עד אשר תנאי מסויים מתקיים, בנתיים היא תציג חלופה. חלופה זו היא הכרחית והיא יכולה להיות בדמות סטרינג או קומפוננטת ספינר למשל. React Suspense עובדת רק עם ייבוא דינמי, כלומר עם lazy loading.
העיקרון שעומד מאחורי lazy loading של רכיבי React הוא טעינת הקוד המינימלי לדפדפן שמציג את דף. הטעינה היא של חלקים קטנים של קוד לפי הצורך. על ידי טעינת פחות קוד JS לדפדפן, זה יביא לביצועים טובים יותר.
React.lazy עושה את זה ממש פשוט להגיד ל-Webpack ולאפליקציה שלנו שניתן לטעון קבצים מסוימים וקוד מסויים מאוחר יותר באפליקציה.
#12 – מהי קומפוננטה מסדר גבוה יותר (Higher-Order Component)?
קומפוננטה מסדר גבוה יותר היא פונקציה שלוקחת קומפוננטה ומחזירה קומפוננטה אחרת. בשונה מקומפוננטה רגילה שמתרגמת מאפיינים לממשק משתמש, קומפוננטה מסדר גבוה יותר מתרגמת קומפוננטה לקומפוננטה אחרת. קומפוננטה מסדר גבוה יותר שכיחות בספריות צד שלישי של React, כמו למשל ה-connect של Redux וה-createFragmentContainer של Relay.
#21 – מה זה children prop?
זהו prop המאפשר להעביר קומפוננטות לקומפוננטות אחרות כמו כל prop אחר. בעיקרון, children prop זה prop מיוחד, המועבר אוטומטית לכל קומפוננטה, וניתן להשתמש בו כדי להציג את התוכן הכלול בין תגי הפתיחה והסגירה של הקומפוננטה.
בהינתן מצב בו אנו רוצים קומפננטת ImageSlider ורוצים שהיא תרנדר דבר כזה:
כפי שניתן לראות ImageSlider מורכבת מכמה תגיות </img> שיכולות להתקבל ולהתרנדר באמצעות props.children:
הודות ל-props.children אנחנו יכולים לקנן את התוכן שלנו בתוך קומפוננטה, בדיוק כמו שאנחנו מקננים אלמנטים אחרים.
הערכים ב-props.children יכולים להיות undefined, null, בוליאני, מספר, סטרינג, אלמנט או מערך של כל אחד מהסוגים הללו באופן רקורסיבי. זה יכול להיות גם פונקציה שמחזירה אחד מהסוגים האלה.
יש לשים לב שבהתאם לדוקומנטציה של ריאקט למרות ש-false, null, undefined ו-true הם children prop חוקיים, ריאקט תתעלם מהם והם לא יוצגו.
#22 – מה זה useMemo?
פונקציית useMemo היא hook אשר ניתן לעטוף אותו סביב פונקציה או אובייקט והוא שומר על הרפרנס של הפונקציה או האובייקט ברנדור מחדש אם הערך שמועבר אליה במערך התלויות (dependencies array) אינו משתנה. כאשר היא עוטפת פונקציה, היא מחזירה רק את הערך שהפונקציה מחזירה והפונקציה לא תיווצר מחדש ולא תרוץ אם הערך במערך התלויות לא השתנה. זה שימושי כאשר יש בקומפוננטה פונקציה איטית וכבדה שאין צורך שתרוץ מחדש בכל רנדור אם המשתנה שהיא מקבלת לא השתנה.
מה שעומד מאחורי זה זה עיקרון ה-memoization – שמירת ערך בקאש כדי שלא יהיה צורך לחשב אותו כל פעם מחדש.
בדוגמה זו הערך של doubleNumber הוא התוצאה שהפונקציה slowFunction מחזירה ולא הפונקציה עצמה.
זה לא מומלץ להשתמש ב-useMemo בכל מקום, כיוון שאם אין בזה צורך אמיתי, כמו בהימנעות מהרצת פונקציה כבדה כל פעם מחדש, אז בכל רינדור של הקומפננטה אנו קוראים ללא צורך לפונציית ה-useMemo ובנוסף לכך שומרים את הערך שהיא מחזירה בזיכרון ומוסיפים עומס על הזיכרון.
שימוש נוסף ל-useMemo הוא בעבודה עם אובייקטים. כידוע אובייקטים נשמרים בזיכרון לא כערכים אלא ברפרנס למקום בזיכרון. בדוגמה שלפנינו בכל רינדור מחדש של הקומפוננטה, ה-themeStyles יהיה אובייקט חדש שנוצר בזיכרון בעל רפרנס אחר לזיכרון, מה שיגרום ל-useEffect לרוץ בכל רנדור מחדש, כיוון שמנקודת מבטו הוא השתנה.
כדי להמנע מכך ניתן לעטוף את האובייקט ב-useMemo וכל עוד הערך במערך התלויות של ה-useMemo, במקרה הזה זה המשתנה "dark", לא ישתנה, לא יווצר אובייקט חדש ויישמר הרפרנס בזיכרון לאותו אובייקט וה-useEffect לא ירוץ ללא צורך.
#23 – מה זה useCallback?
זה hook שעוטף פונקציה ומונע את יצירתה מחדש ברנדור חדש אם הערך שמועבר אליה במערך התלויות (dependencies array) אינו משתנה.
מה ש-useCallback מחזיר זה את כל הפונקציה שהוא עוטף ולא רק את הערך שהפונקציה הזו מחזירה בניגוד ל-useMemo, שמחזיר רק את הערך שהפונקציה מחזירה.
בדוגמה הזו getItems היא פונקציה ולא תוצאת הפונציה בלבד.
כמו כן הפונקציה ש-useCallback עוטפת, יכולה לקבל ארגומנטים:
מתחת למכסה המנוע מה ש-useCallback עושה היא שומרת על הרפרנס של הפונקציה בזיכרון (referential equality) וכל עוד מערך התלויות שלה לא משתנה, יתבצע שימוש בפונקציה השמורה בזיכרון ולא תיווצר פונקציה חדשה בכל רנדור. אחרת יתבצע רנדור מחדש מיותר לקומפוננת הבת אם היא מועברת אליה כ-prop למשל ואז עוברת פונקציה חדשה לגמרי ללא צורך בכל פעם.
מומלץ לעשות שימוש ב-useCallback כאשר הפונקציה היא חלק ממערך התלויות של hook ה-useEffect, או כאשר לפונקציה עצמה יש state פנימי משלה כמו למשל בפונקציית debounce. במקרים כאלה חשוב לשמור על שיוויון ברפרנס של הפונקציה כדי שמערך התלויות לא יזהה שינוי לא מהותי או שערך ה-state הפנימי שלה יישמר.
במקרים בהם יצירת רפרנס חדש של הפונקציה, למרות שהוא גורר רנדור מחדש, אינו צורך משאבים רבים, זה מיותר להשתמש ב-useCallback. יש לזכור שפונקציית useCallback עצמה נקראת בכל רנדור מחדש, אפילו useCallback שמחזיר את אותה פונקציה שהרפרנס שלה נשמר. כמו כן על ידי שימוש מיותר ב-useCallback הקוד נהיה מורכב שלא לצורך.
דוגמה למתי אין צורך להשתמש ב-useCallback:
#24 – מהם הכללים בשימוש ב-hooks?
- ניתן להשתמש ב-hooks רק בקומפוננטות פונקציונליות.
- הם צריכים להיות ב-top level של הקומפוננטה.
- אין להשתמש בהם בתוך בלוקים אחרים של קוד כמו לולאות, תנאים או בפונקציות אחרות.
- הם יוצאים לפועל לפי הסדר שלהם בקוד.
שמירה על כללים אלה מבטיחים שה-hooks יקראו תמיד באותו סדר בכל פעם שהקומפוננטה מתרנדרת. זה מאפשר לריאקט לשמר נכון את ה-state של ה-hooks בין קריאות useState ו-useEffect מרובות.
#25 – מה ההבדל קומפוננטות מבוססות קלאסים לקומפוננטות פונקציונליות?
בגישה הישנה קומפוננטות בריאקט היו קלאסים. בגישה החדשה קומפוננטות יכולות להיות פונקציות וניהול הסטייט נעשה בהן באמצעות ה-hook שנקרא useState.
קומפוננטות פונקציונליות הן פונקציות טהורות (pure function) שמקבלות ארגומנטים בצורת props ומחזירות אלמנטים בצורת JSX.
בקומפוננטות מבוססות קלאסים יש לעשות extend from React.Component וחובה להשתמש בפונקציית render אשר מזירה אלמנטים בצורת JSX.
בקומפוננטות מבוססות קלאסים יש פונקציות life cycle שלא ניתן להריץ בקומפוננטות פונקציונליות. החלופה להן בקומפוננטות פונקציונליות היא בשימוש ב-hook שנקרא useEffect והעברת ארגומנטים למערך התלויות שלו, או החזרת פונקציה בתוכו, מה שגורם לו לפעול בשלבים שונים של חייה של הקומפוננטה.