זהו נושא דיון מלווה לערך המקורי שב־https://www.tocode.co.il/bundles/30/lessons/render-usecallback
לא הבנתי משהו אחד:
למה deleteboxes לא משתנה? הרי כל פעם מוסיפים לרשימה עוד קופסאות שנמחקות.
איך זה קשור ל- ref - שריאקט לא רואה שזה רשימה אחרת??
תודה
הי שושי,
ב JavaScript יש לנו שני סוגי ״פעולות״ שאפשר לעשות עם אוביקטים: פעולות שמשנות את האוביקט עצמו, ופעולות שיוצרות אוביקט חדש על בסיס הקיים. מבחינת ריאקט פעולות שמשנות את האוביקט עצמו (נקרא Mutable) לא מצדיקות render מחדש, כי הכתובת בזיכרון של מבנה הנתונים נשארת זהה.
שימי לב לקוד הבא:
const x = [10, 20, 30, 40];
const y = x;
x.push(50);
הערך של y אחרי הרצת שלושת השורות יהיה המערך כולל האיבר החדש 50, בגלל שגם המשתנה x וגם המשתנה y מצביעים לאותה כתובת בזיכרון, כלומר לאותו מערך. מבחינת ריאקט פעולה כזאת שלא משנה את המקום בזיכרון של אוביקט לא תגרום לשיערוך מחדש של הקומפוננטה. אני מדבר על זה בהרחבה בשיעור הזה:
https://www.tocode.co.il/bundles/react/lessons/state
בחזרה לקבוצות - הפעולה:
deletedBoxes.add(Number(id));
לא משנה את הכתובת בזיכרון ולכן מבחינת ריאקט אם הייתי מפעיל:
setDeletedBoxes(deletedBoxes));
זה פשוט לא היה עושה כלום - הוא היה חושב שאני עושה set לאותו דבר שכבר שמור אצלו. אז בשביל שכן יהיה render מחדש שיניתי את הקוד וכתבתי:
setDeletedBoxes(new Set(deletedBoxes));
כלומר כל פעם שמשתמש ״מוחק״ קופסה אני יוצר Set חדש לגמרי ושולח אותו לפונקציה setDeletedBoxes וככה ריאקט מבין שיש רשימה חדשה ומרענן את האוביקט.
הבעיה עם זה עכשיו היא שהפונקציה removeBox תלויה ב Set שכרגע שמור בסטייט. כל פעם שעושים render מחדש לקומפוננטה יש deletedBoxes חדש (שנוצר עם פקודת ה new). עכשיו אם הייתי צריך להשתמש ב useCallback מסביב ל removeBox היינו מחזיקים תמיד את אותה פונקציה, והיא היתה מסתכלת רק על deletedBoxes הראשון
(ואגב - נסי את זה - קחי את הקוד שהתחלנו איתו ששומר בסטייט את deletedBoxes ותוסיפי useCallback ל removeBox ותראי מה קורה).
בעצם במקום להשתמש ב ref היה אפשר גם להשאיר את deletedBoxes בסטייט אבל לא ליצור Set חדש כל פעם שמוחקים קופסה ובמקום זה להוסיף את המשתנה סטייט החדש renderCounter רק בשביל שנקבל render מחדש אחרי כל מחיקה.
אני מאוד ממליץ שתשחקי עם הקוד הזה כי זה באמת נושא מורכב. תנסי לזהות איך את יכולה לגרום לריאקט לעשות יותר או פחות render-ים ולהעביר משתנים החוצה ופנימה מהקומפוננטה כדי להבין לעומק איך הדברים עובדים.