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

إضافة ترقيم الصفحات (Adding Pagination)

الدرس 21 من 34 · دورة TanStack Router الكاملة · 5 دقيقة و46 ثانية

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

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

الفرع: loaders-2

[00:01] لكن فلنقل الآن إنّنا نحتاج إلى تنفيذ ترقيم الصفحات (pagination) لقائمة منشوراتنا. فلنقل أنّه في عنوان URL لدينا نحتاج إلى أن نكون قادرين على تمرير معامل URL. فلنقل page. وإذا ضبطناه إلى اثنين، على سبيل المثال، فنحتاج إلى تحميل الصفحة الثانية. طبعًا

[00:14] ففي الوقت الحالي لن يفعل هذا أيّ شيء، لأنّنا في دالّة التحميل (load function) لدينا لا نمرّر page هنا.

[00:20] إذًا تذكّر أنّه في هذه الدالّة getPosts.

[00:23] يمكننا تمرير صفحة، وهذا سَيُضيف تخطّيًا (skip) في استدعائي لعنوان URL، وسَتُحمَّل صفحةٌ مختلفة. فأنا أحدّد الحد بـ 10 منشورات هنا، ثم أتخطّى بمقدار رقم الصفحة مضروبًا في 10. فإذا استدعينا هذه الدالّة و

[00:37] مرّرنا إليها ما لَدَينا في معامل URL لدينا، فينبغي أن نُحمّل الصفحة التالية.

[00:41] لكن هناك أمرٌ مهم ينبغي أن تعرفه عندما تحاول الوصول إلى معاملات البحث (search parameters) في دوالّ التحميل عندك.

[00:48] فلنُضِف أولًا معاملَ البحث هذا. لَقَدْ رأينا كيف نفعله من قبل، فلنفعل ذلك بسرعة. إذًا نحتاج فقط إلى استيراد z من Zod. ثم نُعرِّف مخطَّطنا (schema). سَنَمتلك فقط page من النوع number.

[01:01] وسنجعله أيضًا اختياريًّا (optional). وإذا لم يكن موجودًا فسَنَرجِع ببساطة إلى القيمة 1. والآن هنا في مسارنا نحتاج فقط إلى تمرير validateSearch لدينا، وتمريره إلى zodValidator بما أنّنا نستخدم Zod، وبعدُ فلنمرِّر لدينا هذا

[01:16] المخطَّط هكذا.

[01:19] لكن كما ذكرنا، في دالّة التحميل هذه لا يكون لَدَينا وصول إلى معاملات البحث لدينا، ونحتاج إلى الوصول إلى معاملات البحث هنا من أجل الحصول على الصفحة وتمريرها إلى دالّة getPosts. إذًا لماذا لا يكون لَدَينا وصول إلى

[01:31] معاملات البحث هنا؟ في الحقيقة يوجد لذلك سبب. إذًا سَتُخزِّن TanStack Query — كما ذكرنا — البيانات التي نعيدها هنا من دالّة التحميل لدينا. وبما أنّه في حالتنا، فما نعيده في دالّة التحميل لدينا هو ما سَيعتمِد

[01:45] على شيءٍ في معاملات البحث لدينا وهو الصفحة page. وفي هذه الحالة نحتاج إلى أن يكون مفتاح الذاكرة المؤقتة (cache key) لدينا فريدًا بناءً على اسم المسار الذي هو /posts ولكن أيضًا بناءً على الصفحة التي نحاول تحميلها. إذًا عندما نخزّن

[02:01] مسار المنشورات، فنحتاج إلى أن تأخذ الذاكرة المؤقتة التي لدينا في الحسبان أيّ صفحة نخزّنها بالضبط، بحيث أنّه عندما نحاول تحميل صفحة معيّنة سَنحصل على الذاكرة المؤقتة الصحيحة للصفحة الصحيحة. فإذا لم نأخذ هذا

[02:15] معامل البحث الخاصّ بالصفحة في الحسبان عند تخزين بياناتنا مؤقتًا، فقد نحصل على صفحة خاطئة أو بيانات خاطئة عندما نحمّل بياناتنا من الذاكرة المؤقتة. ولا داعي للقلق، فسنتحدث لاحقًا بمزيدٍ من التفصيل عن التخزين المؤقت. فإذا كان لَدَينا وصولٌ إلى معاملات البحث

[02:27] هنا مباشرةً في دالّة التحميل لدينا، فيمكن أن يقود هذا إلى أخطاء (bugs)، لأنّنا نحتاج إلى أن نخبر TanStack Router بشكلٍ ما وبصراحةٍ تامّة بأيّ بياناتٍ في معامل البحث لدينا نعتمد بالضبط لتحميل بياناتنا، حتّى يُخزِّن بياناتنا مؤقتًا بشكلٍ صحيح.

[02:43] إذًا يمكننا فعل ذلك بتحديد تبعيات التحميل (loaderDeps) هنا، وهنا سَنحصل على دالّة، وفي هذه الدالّة سَيَكون لَدَينا وصول إلى معاملات البحث لدينا. إذًا فلنُعِد ببساطة

[02:55] شيئًا هنا، وهنا لَدَينا وصول إلى معاملات البحث ويمكننا إعادة كائنٍ (object) يتضمّن الأشياء التي نعتمد عليها في معاملات البحث. ففي حالتنا هو الصفحة page فقط. إذًا يمكننا إعادة الصفحة في كائنٍ و

[03:11] الوصول إلى الصفحة من معاملات البحث search.page لدينا هكذا.

[03:16] وبفعل ذلك، بما أنّنا نصل إلى search.page هنا، فسَيَكُون هذا تبعيةً (dependency) لدالّة التحميل لدينا وسَيُؤخذ به في الاعتبار عندما نخزّن بياناتنا مؤقتًا. وبما أنّنا نحدّد الآن تبعياتنا هنا في دالّة

[03:29] التحميل لدينا، فسَيَكون لَدَينا وصول إلى هذه التبعيات. إذًا هنا لَدَينا وصول إلى تبعيات (deps) مثل هذا. وفي deps سَيَكون لَدَينا وصول إلى الصفحة page التي نعيدها هنا.

[03:41] وبفعل ذلك بهذه الطريقة، سَيَكون TanStack Router واعيًا بالضبط بما أنت مُعتمِدٌ عليه من معاملات البحث لديك، وينبغي أن يعمل التخزين المؤقت بشكلٍ صحيح بهذه الطريقة. إذًا فلنجرب الآن تحميل صفحاتٍ مختلفة. فلماذا لا

[03:56] نضع، قبلَ عنواننا، مُعرِّفَنا ID هنا — أي post.id — حتى نعرف فقط ونتأكّد أنّك تحمّل منشوراتٍ مختلفة لصفحاتٍ مختلفة.

[04:09] إذًا الآن إذا ذهبنا إلى /posts، فيبدو أنّنا نحصل على الصفحة الثانية.

[04:14] ربّما لديّ خطأ هنا. أه نعم، عذرًا. يجب أن يكون الصفحة page ناقصًا 1 مضروبًا في 10.

[04:21] فحينئذٍ عندما نحمّل الصفحة الأولى فسَيَكون skip لدينا صفرًا. عذرًا عن ذلك.

[04:27] إذًا الآن إذا حدّثنا هنا فينبغي أن نحصل على الصفحة الأولى. والآن إذا وضعنا هنا الصفحة الثانية فينبغي أن نحصل على الصفحة الثانية، والصفحة الثالثة وهكذا. والآن يمكنك ببساطة أن تضيف أزرار ترقيم الصفحات (pagination) هنا لتنقّلك إلى المسار نفسه ومجرّد

[04:46] تحديث هذا المعامل page، ولَقَدْ رأينا كيف نفعله في قسمٍ سابق. فلنأخذ هنا مثالًا سريعًا لإضافة زرّ ربّما للانتقال إلى الصفحة التالية. إذًا هنا في مكوّننا، ربّما بعد حلقة المنشورات،

[05:00] فلربّما نزيل هذه الروابط القديمة. سأضع هذا الرابط (link) هنا حيث ننتقّل إلى مسارنا الحالي وهو مسار post. غير أنّنا نُحدِّث معاملات البحث لدينا فقط. فأنا أمرّر هنا دالّةً (function) حيث سَيَكون لَدَينا

[05:14] معاملات البحث السابقة لدينا. إذًا نزيد الصفحة السابقة ونعود إلى القيمة 1 إذا لم يكن لَدَينا صفحةٌ سابقة. وبالطبع يمكنك فعل الشيء نفسه لزرٍّ للصفحة السابقة.وأنت تعلم أنّه يمكنك إضافة شروط إلى

[05:26] عرض هذه الأزرار أو إخفائها. فإذا كنت في الصفحة الأولى مثلًا فلا ينبغي أن يكون لَدَيك زرّ صفحةٍ سابقة.

[05:32] وإذا كنت في الصفحة الأخيرة فلا ينبغي أن يكون لَدَيك زرّ الانتقال إلى الصفحة التالية وهكذا. فيمكنك إضافة هذه الشروط كذلك. لكن فلنجرب هذا. إذًا الانتقال إلى الصفحة التالية، وكما ترى، يبدو أنّها