לדלג לתוכן

9.4 שליפת נתונים וסרבר אקשנס תרגול

תרגול - שליפת נתונים וסרבר אקשנס - Data Fetching and Server Actions

תרגיל 1 - שליפת נתונים מ-API

צרו דף שמציג רשימת משתמשים מ-API חיצוני:

  • שלפו נתונים מ-https://jsonplaceholder.typicode.com/users
  • הציגו: שם, אימייל, עיר, וחברה
  • עצבו כל משתמש ככרטיס (card)
  • הוסיפו אופציית revalidate של 3600 שניות (שעה)

תרגיל 2 - דף פוסט עם תגובות

צרו דף שמציג פוסט בודד עם התגובות שלו:

  • שלפו פוסט מ-https://jsonplaceholder.typicode.com/posts/{id}
  • שלפו תגובות מ-https://jsonplaceholder.typicode.com/posts/{id}/comments
  • עטפו את התגובות ב-Suspense עם fallback של skeleton
  • הנתיב יהיה /posts/[id]

רמז - שימוש ב-Promise.all לשליפה מקבילית:

const [post, comments] = await Promise.all([
  fetch(`...posts/${id}`).then(r => r.json()),
  fetch(`...posts/${id}/comments`).then(r => r.json()),
]);

תרגיל 3 - טופס יצירת משימה עם Server Action

צרו מערכת משימות (TODO) עם Server Actions:

  • צרו קובץ actions.ts עם הפונקציות: addTodo, toggleTodo, deleteTodo
  • צרו דף שמציג את רשימת המשימות
  • הוסיפו טופס להוספת משימה חדשה (שימוש ב-form action)
  • הוסיפו אפשרות למחיקה וסימון כ"בוצע"
  • השתמשו ב-revalidatePath לעדכון הדף

דמו בסיס נתונים עם מערך:

// lib/todos.ts
let todos = [
  { id: 1, title: "ללמוד Next.js", completed: false },
  { id: 2, title: "לבנות פרויקט", completed: false },
];

export function getTodos() { return todos; }
export function addTodo(title: string) { /* ... */ }
export function toggleTodo(id: number) { /* ... */ }
export function deleteTodo(id: number) { /* ... */ }

תרגיל 4 - סטרימינג עם Suspense

צרו דף דשבורד עם שלושה אזורים שנטענים בנפרד:

  • WeatherWidget - מדמה שליפת מזג אוויר (השהייה של 1 שניה)
  • NewsWidget - מדמה שליפת חדשות (השהייה של 2 שניות)
  • StatsWidget - מדמה שליפת סטטיסטיקות (השהייה של 3 שניות)

כל אחד עטוף ב-Suspense עם skeleton. צפו בטעינה ההדרגתית.


תרגיל 5 - טיפול בשגיאות

שפרו את מערכת המשימות מתרגיל 3:

  • הוסיפו ולידציה ב-Server Action (אורך מינימלי, אין כפילויות)
  • החזירו אובייקט תוצאה עם success/error
  • הציגו הודעות שגיאה בטופס
  • הוסיפו אנימציית loading בזמן שליחת הטופס (useFormStatus)

רמז:

import { useFormStatus } from "react-dom";

function SubmitButton() {
  const { pending } = useFormStatus();
  return (
    <button disabled={pending}>
      {pending ? "שולח..." : "שלח"}
    </button>
  );
}

תרגיל 6 - קאשינג ועדכון

צרו דף שמציג שעה ותאריך נוכחיים מהשרת, ותרגלו קאשינג:

  • צרו פונקציה שמחזירה את הזמן הנוכחי מהשרת
  • צרו שלושה אזורים בדף:
  • אזור סטטי (cache: force-cache) - הזמן לא מתעדכן
  • אזור דינמי (cache: no-store) - הזמן מתעדכן בכל ריענון
  • אזור ISR (revalidate: 10) - הזמן מתעדכן כל 10 שניות
  • הוסיפו Server Action עם revalidatePath שמאפשר ריענון ידני

שאלות

  1. מה ההבדל בין שליפת נתונים ב-Server Component לעומת useEffect ב-Client Component?
  2. מתי נשתמש ב-cache: "no-store" לעומת revalidate?
  3. מה היתרון של Server Actions על פני API Routes?
  4. מה Suspense עושה מאחורי הקלעים בהקשר של סטרימינג?
  5. למה Server Actions תומכים ב-Progressive Enhancement?