دورة TanStack Router الكاملة › دورة TanStack Router الكاملة 1 / 1 السابق التالي

التحقّق من صحة معامِلات البحث باستخدام Zod (Validating Search Params with Zod)

الدرس 14 من 34 · دورة TanStack Router الكاملة · 6 دقيقة و14 ثانية

الفيديو الأصلي باللغة الإنجليزية. إذا تعذّر تشغيله هنا، شاهده على موقع المؤلف. التفريغ النصي العربي الكامل أدناه.

مستودع الكود لهذا الدرس

الفرع: search-2

[00:01] إذا لم تكن معتادًا عليه، فـ Zod مكتبة يمكنها أن تُساعدنا على التحقّق من صحة البيانات (validation) وتحديد أنواعها.

[00:06] وذلك بتعريف مخطط (schema). فيمكننا أن نُعرّف مخططًا كالتالي: لدينا كائن (object) فيه مفتاح (key) اسمه name من نوع string وما إلى ذلك. وباستخدام هذا المخطط يمكننا التحقّق من صحة الكائنات. وفي حالتنا نحتاج إلى التحقّق من صحة كل ما سنمرّره في

[00:19] معامِلات البحث (search parameters). فلنرَ إذًا كيف يمكننا استخدام Zod مع TanStack Router. وبالمناسبة، يدعم TanStack Router مكتبات تحقّق أخرى كذلك، لكن لنستخدم Zod في هذا المثال. وكي نستخدم Zod مع TanStack Router نحتاج

[00:33] إلى تثبيت هذه الحزمة، tanstack ثم مُهايئ Zod (Zod adapter). سيؤدي هذا إلى تثبيت المُهايئ نفسه وكذلك Zod أصلًا. فلنثبّته، عذرًا، ولنرَ بعد ذلك كيف يمكننا استخدامه. فما نحتاج إلى فعله هو أن

[00:52] نُعرّف مخططًا سيحتوي كل ما سنمتلكه في معامِلات البحث لدينا. فلنعرّف مخططًا ونحدّد داخله أنواع هذه الأشياء: sort by وproduct type وpagination وما إلى ذلك. إذًا

[01:08] سأقوم بإنشاء ثابت (constant) هنا.

[01:09] فلنسمّه ربما product search params schema. ونحتاج إلى استيراد z من Zod هكذا. وبالطبع يمكنك — يمكنك — أن تسميته بأيّ اسم؛ إنّه يُسمّى عادةً z هنا فقط، ثم نحتاج إلى كائن داخل مخططنا، فكائن

[01:27] يحتوي على هذه الأشياء. فأوّلها sort by، وهنا يمكننا ربما تمريره كسلسلة نصّية (string). غير أنّه في تطبيقنا سنتمكّن غالبًا من الترتيب حسب أشياء معيّنة مثل السعر (price) أو الشعبية (popularity) وأشياء كهذه. إنها

[01:42] ستكون أشياء محدَّدة سلفًا لا أيّ سلسلة نصّية. ففي Zod يمكن أن يكُون لَدَينا نوع تعداد (enum)، أي z.enum. وهنا يمكننا تمرير القيم في مصفوفة (array). فلنقل ربما newest. ونضيف ربما واحدةً أخرى: oldest. ولنقل ربما

[02:01] price وما إلى ذلك. وهذه هي الفكرة في جوهرها، وأنا شبه متأكد أنّك معتاد على Zod أصلًا. فما سأفعله أنّي سأضع بقية مخططنا هنا ولنمرّ عليه بسرعة. فبالنسبة إلى product type لدينا

[02:15] هذا مصفوفة، فلنمرّره أيضًا كـ enum للنوع، ولنملك ربما enum من قيمتَي shoes وt-shirts مثلًا، ويمكن أن يكون لَدَينا افتراضي (default) كذلك: فلنجعل قيمته الافتراضية shoes. وبامتلاكنا هذا الافتراضي هنا، فإن لم

[02:29] نمرّر هذا في URL لدينا، فسيُستخدم هذا. وسنرى ذلك بعد قليل في pagination.

[02:35] تذكّر أنّه يمكن أن يكُون لَدَينا كائن فيه page وpage size وهما عددان. وهنا لدينا z.object فيه page وpage size، وهما عددان ولديهما قيمة افتراضية أيضًا وهي 1 و10، ثم colors وهي مصفوفة، وهذه المصفوفة لا يمكن أن تحتوي إلا

[02:52] على هذه الأشياء: فـ enum من red وblue وgreen، ويمكننا جعل هذا اختياريًا (optional). أجعله اختياريًا بتمرير optional هنا، ثم sale وهي boolean، ولنجعلها افتراضيًا أيضًا true.

[03:06] فيمكنك أن تضع ما تشاء هنا.

[03:07] لكن الآن بعد أن أصبح لَدَينا مخططًا، فلنرَ كيف يمكننا استخدامه. ففي دالة validate search هذه، بدلًا من تمرير دالة والقيام بتحديد الأنواع والقيم الافتراضية بأنفسنا، يمكننا ببساطة إزالة هذا. الآن، الآن بعد أن أصبح لَدَينا

[03:21] الأنواع محدَّدة هنا، ونمرّر Zod validator (مُحقِّق Zod) الذي يمكننا استيراده من هذه الحزمة التي ثبّتنّاها، صحيح؟

[03:30] ثم نمرّر له المخطط. وقد سمّيناه — أظنّ، نعم — product search params schema. فيمكننا تمريره هنا، وبمجرّد ذلك الآن، في URL لدينا، لنجرب أن لا نمرّر شيئًا في خاصية (prop) search، وسنحصل

[03:50] على خطأ. لماذا نحصل على خطأ؟ لأنّنا هنا نحدّد أنّ sort by من نوع enum، غير أنّه لا توجد قيمة افتراضية له، ولا نصنّفه اختياريًا، على نحو مماثل لما نفعله هنا. فـ sort by علينا

[04:05] تمريره. فإذا مرّرنا sort by فلن نحصل على أيّ أخطاء. والآن إذا انتقلنا إلى هذا الرابط: فلنذهب إلى home ثم ننتقل إلى هذا. وكما ترى في URL لدينا، لن نحصل على sort

[04:21] by وحده، بل سنحصل أيضًا على القيم الافتراضية لبقية الأشياء الموجودة في معامِلات البحث لدينا.

[04:29] وإذا تطلّعت إلى السجلّات (logs) هنا — وتذكّر أنّنا في مكوّننا نسجّل معامِلات البحث الموجودة في URL لدينا — فسنحصل على ما مرّرناه في sort by، لكننا سنحصل أيضًا

[04:42] على الافتراضات؛ تذكّر أنّه في product type كان لَدَينا افتراض shoes، فنحصل على هذه هنا.

[04:48] وكذلك في pagination كانت لَدَينا قيم افتراضية لـ page وpage size، فنحصل عليهما هنا كذلك.

[04:55] وكذلك في sale وضعناها افتراضيًا — وضعناها افتراضيًا — على true، فنحصل عليها هنا، صحيح. أما colors، فتذكّر أنّنا جعلناها اختيارية، فقد لا تكون لَدَينا هنا؛ فنوع colors سيكُون مصفوفة أو undefined. فبجعل

[05:12] هذا اختياريًا، لن يكُون من المضمون أن نحصل عليه في معامِلات البحث. فإذا تطلّعنا في مكوّننا إلى نوع معامِلات البحث لدينا، فسنرى undefined هنا في colors. غير أنّه بالنسبة إلى أيّ شيء نملكه

[05:26] وهو ليس اختياريًا، أو لَدَينا له افتراض، فلن يكون undefined؛ بل يكون وجوده مضمونًا في كائن search هذا حتى لو لم نمرّره هنا صراحةً.

[05:39] ولنجرب أيضًا، ربما، تمرير شيئًا خارج قيم enums لدينا. تذكّر أنّنا هنا حدّدنا newest وoldest وprice.

[05:48] إذا مرّرنا شيئًا آخر فسنحصل على خطأ TypeScript. وبالطريقة نفسها هنا، إذا مرّرنا — أظنّ أنّ لدينا مشكلة هنا. أوه، أجل، إنّ هذا enum وليس مصفوفة من enums. فعلينا إمّا أن نمرّر

[06:04] shoes أو t-shirts، وإذا مرّرنا شيئًا آخر فسنحصل على خطأ. وفي pagination مثلًا إذا مرّرنا هنا شيئًا خاطئًا فسنحصل على خطأ، وهكذا دواليك.