9.3 קומפוננטות שרת וקליינט תרגול
תרגול - קומפוננטות שרת וקליינט - Server and Client Components¶
תרגיל 1 - זיהוי סוג הקומפוננטה¶
לכל אחת מהקומפוננטות הבאות, החליטו אם היא צריכה להיות Server Component או Client Component, והסבירו למה:
- קומפוננטה שמציגה רשימת מוצרים מבסיס נתונים
- קומפוננטה עם טופס הרשמה (שדות קלט וכפתור שליחה)
- קומפוננטה שמציגה שעון בזמן אמת
- קומפוננטה שקוראת קובץ JSON מהשרת ומציגה אותו
- קומפוננטה עם אקורדיון (פתיחה/סגירה של תוכן)
- קומפוננטה שמציגה תוכן Markdown שהומר ל-HTML
ממשו כל אחת מהקומפוננטות (לפחות 4 מתוך 6).
תרגיל 2 - הפרדת שרת וקליינט¶
בניתם קומפוננטה אחת שעושה הכל. פצלו אותה נכון:
// לפני - קומפוננטה אחת שגויה
"use client";
import { prisma } from "@/lib/prisma";
import { useState } from "react";
export default async function ProductsPage() {
const products = await prisma.product.findMany();
const [search, setSearch] = useState("");
const filtered = products.filter(p =>
p.name.includes(search)
);
return (
<div>
<input value={search} onChange={e => setSearch(e.target.value)} />
<ul>
{filtered.map(p => <li key={p.id}>{p.name}</li>)}
</ul>
</div>
);
}
פצלו לשתי קומפוננטות:
- Server Component ששולף את הנתונים
- Client Component שמנהל את הסינון והחיפוש
תרגיל 3 - תבנית Provider¶
צרו מערכת theme (בהיר/כהה) לאפליקציה:
- צרו Client Component בשם
ThemeProviderשמספק context של theme - צרו Client Component בשם
ThemeToggleעם כפתור למעבר בין בהיר לכהה - ודאו שה-layout הראשי (Server Component) עוטף את כל האפליקציה ב-Provider
- השתמשו בתבנית children כדי שדפי Server Component ימשיכו לעבוד
תרגיל 4 - דף פרופיל מורכב¶
צרו דף פרופיל (/profile) עם המבנה הבא:
- הדף עצמו הוא Server Component ששולף את נתוני המשתמש
- קומפוננטת
ProfileHeader(Server) - מציגה שם ותמונה - קומפוננטת
ProfileStats(Server) - מציגה סטטיסטיקות (פוסטים, עוקבים) - קומפוננטת
EditProfileForm(Client) - טופס עריכה עם useState - קומפוננטת
ProfileTabs(Client) - טאבים (פוסטים, תגובות, לייקים)
דמו את הנתונים מהשרת (אין צורך בבסיס נתונים אמיתי).
תרגיל 5 - גבולות סריאליזציה¶
תקנו את הבעיות בקוד הבא. כל אחד מהמקרים מנסה להעביר משהו שלא ניתן לסריאליזציה:
// מקרה 1
export default function Page() {
const formatPrice = (price: number) => `${price} ש"ח`;
return <PriceDisplay format={formatPrice} price={100} />;
}
// מקרה 2
export default function Page() {
const settings = new Map([["theme", "dark"], ["lang", "he"]]);
return <Settings data={settings} />;
}
// מקרה 3
export default function Page() {
const regex = /^[a-z]+$/;
return <Validator pattern={regex} />;
}
שאלות¶
- מה קורה כשמייבאים Server Component לתוך Client Component?
- למה Client Components עדיין עוברים SSR?
- מה ההבדל בין העברת Server Component כ-children לעומת יבוא ישיר ב-Client Component?
- איך
"use client"משפיע על קבצים שמיובאים לתוך הקובץ? - האם כל הקוד של Client Component רץ רק בדפדפן?