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

حماية مسارات متعدّدة باستخدام التخطيطات (Protecting Multiple Routes with Layouts)

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

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

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

الفرعان: auth-2 · auth-3

[00:01] لحماية مسارات متعدّدة بتخطيط (layout)، نحتاج إلى إضافة أصل (parent) للمسارات التي نحتاج إلى حمايتها. وهذا الأصل يمكن أن يكون تخطيطًا بلا مسار (pathless layout)، أو مجرّد مسارًا أصليًّا عاديًّا يمكن أن يمتلك مسارًا (path)

[00:15] أيضًا. إذًا فلنرجع إلى هذا الموضع ولنقل أنّه في مسار about لدينا سأزيل هذه الحماية الّتي لَدَينا هنا.

[00:23] إذًا الآن about لم يعد محميًّا. وفلنجري هذا بالطريقة الأخرى. إذًا الآن — فلنسجّل الخروج بدايةً في ملفّ main.tsx لدينا أيضًا، بتغيير هذا مجدّدًا إلى null هكذا.

[00:40] إذًا الآن ينبغي أنّنا خارج وضع تسجيل الدخول ويمكننا الوصول إلى about بما أنّنا أزلنا هذه الحماية.

[00:47] الآن، ما يمكننا فعله هو أنّنا نفعل ذلك ربّما بتخطيط بلا مسار: فلنمتلك تخطيطًا بلا مسار يجري فحوص المصادقة، ثم إذا احتجنا إلى حماية أيّ مسار نجعله ببساطة ابنًا (child) لهذا التخطيط. إذًا من هنا

[01:03] فلنذهب إلى مجلّد routes لدينا ولننشئ هذا التخطيط بلا مسار. تذكّر أنّنا لفعل ذلك نستخدم الشرطة السفلية (underscore)، ولنسمّيه ربّما — المصادَق عليه (authenticated) — ما، ‏_authenticated.tsx.

[01:21] ومن هنا لن نفعل أيّ شيء. سَنصيّر ببساطة المخرَجَ (outlet) لدينا كي نتمكّن من تصيير أبنائنا (children). غير أنّه في الترميز (markup) لن نفعل أيّ شيء آخر. غير أنّ ما سَنفعل هو

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

[01:44] من هنا.

[01:46] ولنجعل هذا مُزالًا من about حتى ننجزه عبر التخطيط.

[01:51] إذًا من هنا فلنلصق هذا، استيراد redirect.

[01:56] وأظنّ أنّ هذا ينبغي فعلًا أن يكون كلّ شيء.

[02:00] الآن، بإضافة هذا كأصل لأيّ مسار، سَتُشغَّل هذه الدالّة beforeLoad أولًا قبل تصيير أيّ من الأبناء. وإذا لم تكن مسجّلَي الدخول فسَنُعاد التوجيه، ولن يُحمَّل أو يُصيَّر أيّ من

[02:12] الأبناء. وهكذا يمكننا حماية مساراتنا بهذه الطريقة. فلنجري ذلك في مسار about بجعل about ابنًا لهذا التخطيط المصادَقَ عليه. فلننسخ الاسم فعلًا من هنا. ولنُعِدِ في هنا تسمية about إلى

[02:31] ‏_authenticated.about.

[02:34] والآن ينبغي فعلًا أن يكون ابنًا لهذا التخطيط — ابنًا لهذا التخطيط.

[02:40] وكما ترى، إذا حاولنا الوصول إلى about فينبغي أن يكون محميًّا الآن. سَيُعاد توجيهنا إلى login مع معامِل البحث redirect لدينا كذلك. لماذا لا نجرّب ذلك ربّما أيضًا مع مسار آخر كذلك؟

[02:56] إذًا فلنقل random word. هذا يمكنني الوصول إليه لأنّه ليس محميًّا. فلنقل أنّنا نحتاج إلى أن يكون محميًّا؛ علينا حينئذ إعادة تسمية هذا ببساطة ووضع تخطيطَنا المصادَقَ عليه (authenticated) قبل random word.

[03:15] محميًّا كما ترى وسَنُعاد التوجيه إلى login بمعامِل redirect بقيمة random word.

[03:24] خيار آخر نملكه هو أنّه ربّما، عندما تحاول الوصول إلى مسار محميّ، بدلًا من إعادة التوجيه إلى login تحتاج فحسب إلى عرض خطأ (error). إذًا ما يمكننا فعله هو أنّه ربّما نعلّق دالّة beforeLoad مؤقتًا في تخطيطنا

[03:37] المصادَقَ عليه. إذًا لن يكون هناك أيّ شيء محميًّا الآن. يمكننا الوصول إلى about بشكل عادي.

[03:43] فلنذهب إلى /about ويجب أن نتمكّن من الوصول إلى about. لنقل أنّنا نحتاج فحسب إلى عرض رسالة (message) تفيد بأنّنا لا نملك وصولًا بدلًا من إعادة التوجيه إلى login. إذًا ما يمكننا فعله هو أنّه في مكوّننا الأب

[03:58] المكوّن، تخطيطنا المصادَقَ عليه: بدلًا من تصيير الأبناء، يمكننا أن نُصيّر هذه الرسالة بدلًا منهم. وتذكّر أنّ لَدَينا من هذا المكان وصولًا إلى سياقنا بوساطة الخطّاف. إذًا يمكننا الوصول من مسارنا — عذرًا — من route.useRouteContext.

[04:14] يمكننا جلب مستخدمنا من هنا ويمكننا إجراء فحصنا من هنا كذلك. فلنضف ربّما هذا الشرط من هنا: إن لم يكن لَدَينا مستخدم (user)، سَنعيد بدلًا من ذلك هذا div.

[04:25] وكما ترى، فهذا يعمل. فلنجربه أيضًا مع random word. ويبدو أنّه يعمل كذلك. غير أنّه إذا نظرنا إلى شبكتنا (network) من هنا — فلنذهب إلى about، ولنُفرِّغ لوحة الشبكة، ثم ننتقل إلى random word. وكما ترى،

[04:42] لا نرى — بل سَنرى هذه الرسالة.

[04:44] غير أنّ طلب الشبكة الخاص بـ random word أُرسل.

[04:50] وهذا ليس جيدًا. بالطبع، إذا كان لَدَينا مسار محميّ فعلينا منع دالّة التحميل لهذا المسار المحميّ من التشغيل: حتى وإن — حتى لو لم نعرض أيّ مضمون، فعلينا منع دالّة التحميل من

[05:03] التشغيل. إذًا يمكننا إمّا أن نذهب إلى مسار random word لدينا، ونحن لَدَينا في دالّة التحميل لدينا وصول إلى سياقنا من هنا، فربّما قبل تحميل أيّ بيانات نفحص سياقنا ونؤكّد أنّنا مسجّلُو الدخول.

[05:20] أو بدلًا من الاضطرار إلى فعل هذا لكلّ مسار محميّ، يمكننا كذلك — بدلًا من عرض رسالتنا هكذا — أن نُرجِع دالّة beforeLoad إلى التخطيط لدينا، في تخطيطنا

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

[05:49] إذًا برمينا خطأً هنا فإنّ هذا سَمنع أي دالّة تحميل لأيّ من الأبناء من التشغيل. إذًا فلنرمِ خطأً (error) جديدًا ولنسمِّه ربّما auth error أو ما شابه. وإذا حفظنا هذا الآن وحاولنا الوصول إلى random word مثلاً

[06:08] فسَنحصل على الخطأ هكذا. لن نحصل على هذه الرسالة لأنّ هذا المكوّن لن يكون مُصيَّرًا أصلًا. فما نحتاج إلى فعله بدلًا من ذلك هو تمرير مكوّن خطأ (error component)، وداخل مكوّن الخطأ يمكنك فحص

[06:21] الخطأ، تفحص إن كان خطأً مصادقة؛ يمكنك عرض خطأ مصادقة لأنّه قد يكون خطأً آخرُ كذلك — غير أنّي سأُبقي الأمر بسيطًا وأفترض أنّ لَدَينا خطأً مصادقةً وأنّني أعرض فحسب

[06:34] هذه الرسالة في مكوّن الخطأ (error component) لدينا. إذًا الآن إذا عاودنا التحديث فينبغي أن نحصل على هذا.

[06:42] والآن يمكننا ربّما إزالة هذا الفحص من هنا.

[06:51] حسنًا.

[06:51] وكذلك للتأكّد فلننتقل إلى about ثم ننتقل إلى random word. وكما ترى، لا شيء يُرسَل في شبكتنا. ولنجرب أخيرًا أيضًا النقر على login من هنا.

[07:03] وسَيعيد هذا تحميل مسار لدينا وسيعمل الآن. إذًا هذا في الأساس