לדלג לתוכן

7.1 useRef, useMemo ו useCallback תרגול

תרגול - useRef, useMemo ו-useCallback


תרגיל 1 - טיימר עם useRef

צרו קומפוננטת טיימר שמציגה שניות, עם כפתורי התחלה, עצירה ואיפוס.

דרישות:
- שמרו את ה-interval ID ב-useRef
- הציגו את הזמן בפורמט דקות:שניות (לדוגמה 02:35)
- וודאו שה-interval מתנקה כש-component מתפרק (cleanup)
- הוסיפו כפתור "הקפה" (lap) ששומר את הזמן הנוכחי ברשימה


תרגיל 2 - טופס עם פוקוס אוטומטי

צרו טופס הרשמה עם שדות: שם, אימייל וסיסמה.

דרישות:
- כשהקומפוננטה עולה, הפוקוס עובר אוטומטית לשדה השם
- כשהמשתמש לוחץ Enter בשדה אחד, הפוקוס עובר לשדה הבא
- כשהמשתמש לוחץ Enter בשדה האחרון, הטופס נשלח
- השתמשו ב-useRef לכל שדה ו-forwardRef לקומפוננטת שדה מותאמת


תרגיל 3 - רשימה מסוננת וממוינת עם useMemo

יצרו קומפוננטה שמציגה רשימת עובדים עם אפשרות סינון ומיון.

דרישות:
- הרשימה מכילה: שם, מחלקה, שכר, תאריך תחילת עבודה
- אפשרות סינון לפי שם (חיפוש חופשי) ולפי מחלקה (dropdown)
- אפשרות מיון לפי שם, שכר או תאריך
- הציגו סטטיסטיקות: ממוצע שכר, שכר מקסימלי ומינימלי (של התוצאות המסוננות)
- השתמשו ב-useMemo לסינון, מיון ולחישוב הסטטיסטיקות

נתוני דוגמה:

const employees = [
  { id: 1, name: "דני", department: "פיתוח", salary: 25000, startDate: "2020-03-15" },
  { id: 2, name: "מיכל", department: "עיצוב", salary: 22000, startDate: "2021-07-01" },
  { id: 3, name: "יוסי", department: "פיתוח", salary: 28000, startDate: "2019-01-10" },
  { id: 4, name: "שרה", department: "שיווק", salary: 20000, startDate: "2022-05-20" },
  { id: 5, name: "אבי", department: "פיתוח", salary: 30000, startDate: "2018-11-03" },
  { id: 6, name: "רונית", department: "עיצוב", salary: 24000, startDate: "2020-09-12" },
  { id: 7, name: "גל", department: "שיווק", salary: 21000, startDate: "2023-01-15" },
  { id: 8, name: "נועה", department: "פיתוח", salary: 27000, startDate: "2021-03-28" },
];

תרגיל 4 - רשימת משימות עם useCallback

צרו רשימת משימות (Todo List) אופטימלית.

דרישות:
- כל פריט ברשימה הוא קומפוננטה נפרדת עטופה ב-React.memo
- הוסיפו console.log לכל רנדר של פריט כדי לוודא שרק הפריטים שהשתנו מרונדרים
- פעולות: הוספה, מחיקה, סימון כהושלם, עריכת טקסט
- השתמשו ב-useCallback לכל הפונקציות שמועברות כ-props לילדים
- הוסיפו מונה רנדרים (useRef) שמציג כמה פעמים הקומפוננטה הראשית רונדרה


תרגיל 5 - חיפוש עם Debounce

צרו קומפוננטת חיפוש שמדמה שליחת בקשה לשרת.

דרישות:
- שדה חיפוש שמחפש רק אחרי שהמשתמש הפסיק להקליד ל-500 מילישניות (debounce)
- השתמשו ב-useRef לשמירת ה-timeout ID
- השתמשו ב-useCallback לפונקציית החיפוש
- השתמשו ב-useMemo לסינון התוצאות
- הציגו מצב טעינה (loading) בזמן ה-debounce


תרגיל 6 - גלריית תמונות עם Intersection Observer

צרו גלריית תמונות עם טעינה עצלה (lazy loading).

דרישות:
- הציגו רשימת תמונות (אפשר להשתמש ב-placeholder מ-https://picsum.photos)
- השתמשו ב-useRef וב-Intersection Observer כדי לטעון תמונות רק כשהן נכנסות לתצוגה
- הוסיפו אנימציית fade-in כשתמונה נטענת
- השתמשו ב-useCallback לפונקציית ה-callback של ה-observer
- הציגו מונה של כמה תמונות נטענו מתוך הסך הכולל


שאלות

  1. מה ההבדל בין שמירת ערך ב-useState לעומת useRef? מתי נעדיף כל אחד?
  2. האם useMemo מבטיח שהחישוב ירוץ פעם אחת בלבד? מה ריאקט עשויה לעשות עם ערכים ששמרנו ב-useMemo?
  3. למה useCallback לבד, ללא React.memo על הקומפוננטה שמקבלת את הפונקציה, לא באמת משפר ביצועים?
  4. מה הקשר בין useCallback ל-useMemo? האם אפשר לממש את useCallback באמצעות useMemo?
  5. מהם הסיכונים של שימוש יתר ב-useMemo ו-useCallback?