الاختيار · فصل ٨

الـ safeParse في الـ API ولا الـ UI؟

API layer · throw · isPending · isError · InvalidApiResponseError
🎯 الهدف: تحط التحقق من الـ API response في الـ API layer، وتخلي الـ UI يتعامل مع pending وerror وdata، وترمى خطأ واضح لما الشكل غلط.

المكان المعتاد هو الـ API layer

الجزء ده مكانه بيعتمد على إنت عايز تعمل إيه بالـ validation error. في الحالة المعتادة مع React وTanStack Query، الأفضل تعمل الـ validation في الـ API layer، مش في الـ UI.

users.api.ts
import { userSchema } from "./users.schema";export async function getUser() {  const response = await fetch("/api/user");  if (!response.ok) {    throw new Error("Failed to fetch user");  }  const data: unknown = await response.json();  const result = userSchema.safeParse(data);  if (!result.success) {    console.error("Invalid API response:", result.error);    throw new Error("INVALID_API_RESPONSE");  }  return result.data;}

إيه اللي حصل هنا؟

  • الـ API رجعت الداتا.
  • عملنا validation بـ safeParse.
  • لو الداتا غير صحيحة، رمينا Error.
  • لو صحيحة، رجعنا result.data، وTypeScript عارف نوعها بالفعل.
استخدمنا throw بدل return في حالة الخطأ، عشان TanStack Query تعتبر الـ request فاشلة، مش ناجحة ببيانات ناقصة.

الـ UI بيعرض النتيجة بس

UsersList.tsx
const userQuery = useQuery({  queryKey: ["user"],  queryFn: getUser,});if (userQuery.isPending) {  return <p>Loading...</p>;}if (userQuery.isError) {  return <p>تعذر تحميل بيانات المستخدم</p>;}return <h1>{userQuery.data.name}</h1>;

الـ UI مش محتاج يعرف تفاصيل Zod أو يفحص الداتا بنفسه. هو بيتعامل مع النتيجة النهائية:

  • isPending: بيحمّل.
  • isError: حصل خطأ في الـ request أو الـ validation.
  • data: داتا اتعملها validation بنجاح.

إمتى safeParse في الـ UI؟

غالبًا مش هتحتاج. الـ UI المفروض يستهلك داتا موثوقة من الـ API layer.

ممكن تستخدمه في الـ UI لو بتتعامل مع مصدر بيانات محلي أو خارجي بشكل منفصل، زي بيانات جاية من localStorage أو إدخال المستخدم قبل عرضها.

مين مسؤول عن إيه؟

المسؤوليةمكانها
التحقق من الـ API responseAPI layer
تحويل أخطاء الـ validation إلى errors يفهمها التطبيقAPI layer أو طبقة مركزية للأخطاء
عرض رسالة الخطأ المناسبة للشاشةUI
تسجيل تفاصيل الخطأ ومراقبتهError logging / monitoring layer

خلّصت الفصل لما

🧠 اختبر نفسك
١) ليه throw مش return لما safeParse يفشل؟
عشان TanStack Query تعتبر الطلب فاشل، مش ناجح بداتا ناقصة.
٢) الـ UI يفحص Zod بنفسه؟
لأ. يستهلك داتا اتفحصت في الـ API layer، ويعرض loading أو error أو الداتا.
٣) إمتى safeParse في الـ UI؟
مع مصدر منفصل زي localStorage أو إدخال المستخدم قبل العرض.