تداخل المسارات (Nesting Routes)
الدرس 6 من 34 · دورة TanStack Router الكاملة · 9 دقيقة و52 ثانية
الفيديو الأصلي باللغة الإنجليزية. إذا تعذّر تشغيله هنا، شاهده على موقع المؤلف. التفريغ النصي العربي الكامل أدناه.
مستودع الكود لهذا الدرس
الفرع:
nesting-routes
[00:02] لكي نُنشئ مسارات متداخلة (nested routes) في موجّه (router) TanStack Router. يمكننا فعل ذلك ببضع طرق. أولًا، يمكننا بمجرد إنشاء مجلدات أو أدلّة (directories) وتداخل بعضها داخل بعض، وهكذا سيكون لدينا ببساطة مسارات متداخلة. أو يمكننا تسمية ملفنا
[00:16] بطريقة معيّنة سَتَدُلّ على أنّ مسارًا ما متداخل داخل مسارٍ آخر. لكن لِنبدأ أولًا، ربّما، بالأبسط والأكثر مباشرةً، وهي استخدام المجلدات. فلتقل مثلاً أنّه في مجلد routes لدينا
[00:29] مجلد آخر اسمه settings. الآن داخل settings يمكننا إنشاء مسارات متداخلة، فلتقل أنّنا سنمتلك settings/profile على سبيل المثال، أي profile.tsx داخل settings.
[00:42] وكما تلاحظ، وُلِّد هذا لنا تلقائيًا (autogenerated)، والمسار سَيَكُون settings/profile.
[00:49] لكن الآن، لنقل أنّنا سنمتلك أيضًا مسارًا آخر داخل settings، فلنقل payment.tsx.
[01:00] وسَيَكُون لدينا هذا مُولَّدًا لنا أيضًا، وبالمسار settings/payment.
[01:04] في الشيفرة المولَّدة تلقائيًا لدينا عنصر div هذا. سأضيف بضعة أصناف (classes) كي أتمكّن من رؤية الأشياء، مجرد بعض لون الخلفية وحاشية (padding) وما إلى ذلك.
[01:12] وهكذا بالنسبة إلى payment، ولنفعل الشيء ذاته أيضًا للأخرى، وهي profile، هكذا.
[01:21] الآن لِنفتح، ربّما، أدوات المطوّر (devtools)، ويمكننا أن نرى هنا في شجرتنا أنّ لدينا الآن بضعة مسارات: settings/payment وsettings/profile، لكن لاحظ أنّنا لا نمتلك settings
[01:36] بذاتها. لذا يمكننا الذهاب إلى settings/payment وهذا ما سنراه، ويمكننا الذهاب إلى settings/profile.
[01:43] وسنحصل على هذا. غير أنّه إذا انتقلنا إلى settings نفسها بلا شرطة مائلة (slash) أو أيّ شيء بعدها، فسيكون هذا المسار غير موجود (not found). لكن لنقل أنّنا نحتاج إلى مطابقة settings أيضًا بلا أيّ مقطع (segment) آخر. يمكن فعل ذلك ببضع طرق، نحن
[01:58] يمكن أن نجعل settings مسارًا بذاته، أو أن نجعلها أبًا (parent) لـ settings/profile وsettings/payment. فِلتَحاوِل أن تُصوّر ذلك.
[02:11] إذًا تخيّل أنّ لَدَينا شجرتنا، ولَدَينا مسار الجذر (root route) الذي سَيَظلَّ موجودًا دائمًا. ويمكن أيضًا أن تكون لَدَينا مسارات home وabout وما إلى ذلك. لكن لِنركّز الآن على المسار الذي أنشأناه للتوّ، وهو هذا. فلنقل
[02:24] أنّ هذه هي settings.
[02:27] فيمكن أن يكون لَدَينا settings، وهو حاليًا غير مطابَق (not matched)، ويمكن أن نجعله أبًا للمسارين الآخرين، وهما payment وprofile أو غيرهما، أو يمكن أن نجعله مسارًا بذاته. إذًا يمكن أن يكون لَدَينا مسار الجذر، ثم
[02:45] يمكن أن نجعل settings مسارًا بذاته لا أبًا، ثم أن يكون لَدَينا settings/profile وsettings/payment. كلّ هذه ستكون ثلاثة مسارات منفصلة. وبالطبع، بحسب ما تحتاج، يمكنك اختيار أحد هذين
[02:58] النهجين. إذا اخترت هذا الذي يكون فيه settings أبًا، فسيتعيّن عليك تصيير (render) مكوّن Outlet (المنفذ)، لأنّ settings سَتُطابَق الآن من أجل settings ومن أجل settings/profile ومن أجل settings/payment.
[03:11] إذًا المكوّن (component) الذي ستعرفه هنا سَيَظلَّ موجودًا لكل هذه المسارات، وإذا كان لَدَينا أبناء (children)، فسنحتاج إلى تصيير Outlet لعرض أبنائنا.
[03:21] على نحو مماثل لما لَدَينا في مسار الجذر وأبنائه. غير أنّه إذا فعلناها بهذه الطريقة، فسَتَكُون settings الآن مسارًا منفصلًا، ولن نحتاج إلى وجود Outlet، لأنه لن يملك أيّ أبناء. فِلَنرَ ذلك عمليًا.
[03:37] لِنجرب أوّلًا، ربّما، النهج الذي سَتَكُون فيه لَدَينا ثلاثة مسارات منفصلة، أليس كذلك؟ ولِفعل ذلك، يمكننا الذهاب إلى مجلدنا، وداخل settings، حتى يُطابَق settings، يمكننا إنشاء ملف
[03:52] index.tsx هنا. ولاحظ أنّه عندما نفعل ذلك، فسيظهر المسار المُنشَأ هنا حاملًا شرطةً مائلةً لاحقةً (trailing slash) في نهايته. وهذا يعني أنّ هذا المكوّن أو هذا المسار سَيُطابَق فقط إذا كان عنوان URL لدينا
[04:08] بالضبط /settings وليس /settings مع أيّ شيء آخر. فبهذه الطريقة تكون /settings مجرد ابن (child) لمسار الجذر، وهي ليست أبًا لـ settings/شيء ما. فإذا تطلّعنا هنا إلى أدوات المطوّر، فسنجد أنّ لَدَينا
[04:28] settings كأخٍ (sibling) لـ settings/profile وsettings/payment، وهي ليست أبًا، أليس كذلك؟ ولن يُطابَق ذلك المسار. إنها حاليًا خضراء لأن عنوان URL لدينا هو settings بالضبط.
[04:41] غير أنّه إذا ذهبنا إلى settings/profile، فلن يكون هذا أخضر، ولن يُطابَق، أليس كذلك؟ فبهذه الطريقة يكون settings مسارًا منفصلًا لا صلة له إطلاقًا بـ settings/profile وsettings/payment.
[04:56] تمام؟ لكن ماذا لو أردنا هذا النهج الآخر، حيث يتصرّف settings بمثابة تخطيط (layout) لأي مسار يبدأ بـ settings/شيء ما؟
[05:07] الآن، في هذه الحالة، بدلًا من index.tsx، سيتعيّن علينا إعادة تسميته إلى route.tsx.
[05:13] إذًا لِنُعِد هنا تسمية هذا إلى route.tsx.
[05:19] والآن، وكما تلاحظ هنا في الملف المولَّد، لم نَعُد نملك تلك الشرطة المائلة اللاحقة، وهذا يعني أنّ هذا المسار، أو هذا المكوّن، سَيُطابَق مع أيّ شيء يبدأ بـ settings، وطبعًا
[05:34] مع settings نفسها. فإذا تطلّعنا إلى أدوات المطوّر، فسنلاحظ الآن أنّ settings أصبحت أبًا لـ payment ولـ profile، وأيضًا عندما نزور settings/profile
[05:49] يكون settings مطابَقًا، أي أخضر، وprofile أخضر أيضًا. وإذا ذهبت إلى payment فسَيَكُون settings أخضر، وpayment أخضر. أما إذا ذهبت إلى settings وحدها، بالنقر على هذا السهم، فسَيَكُون settings وحده أخضر، وسنحصل
[06:06] على صفحة settings. أما إذا ذهبنا إلى payment أو profile فلن يتغيّر شيء هنا، لأنّ settings، بما أنها صارت أبًا لـ profile ولـ payment، نحتاج الآن إلى تصيير Outlet.
[06:16] صحيح؟ لذا في settings ثم في route.tsx نحتاج إلى وضع Outlet هنا كي نصيّر أبناءنا. فيمكننا استيراد (import) Outlet، ووضعه هنا، وحفظ، وستظهر لنا أشياءُنا. ويمكننا الانتقال إلى payment وprofile وما إلى ذلك.
[06:35] مع ذلك، المكوّن الذي عرّفناه داخل settings — عذرًا، داخل route.tsx في settings — سَيَظلَّ موجودًا دائمًا، وهو هذا. فنحن لَدَينا مسار الجذر، ولَدَينا settings، ثم المسار الذي نزوره،
[06:50] سواءً كان payment أو profile، صحيح. ويمكننا أيضًا، ربّما، أن نضيف بعض الشيفرة هنا للتنقّل بين payment وprofile داخل settings. ففي settings بوصفها أبًا أو تخطيطًا يمكننا ربّما أن نضع هنا
[07:10] هذا div، مع هذا الاستيراد لـ Link (الرابط) الذي سَيَذهب إلى settings/payment أو إلى settings/profile.
[07:18] وطبعًا — بالمناسبة، بما أنّ لدينا الآن مسارات أكثر — سَنَحصُل على هذه أيضًا في الإكمال التلقائي (autocomplete) وما إلى ذلك. والآن إن حفظنا هذا، فسيتوفر لنا هذه روابط تنقّل بواسطتها يمكننا
[07:31] التنقّل داخل settings بين payment وprofile.
[07:35] لكن الآن لنقل أنّ لَدَينا حالة يكون فيها لَدَينا مسار settings/شيء ما أيضًا، ومع ذلك نحتاج ألّا يستخدم هذا المسار الجديد مسارَ settingsَ أبًا له. فلتقل أنّ لَدَينا مسارًا آخر هو settings/شيء ما كذلك، لكننا نحتاج
[07:54] إلى أن يكون ابنًا مباشرًا (direct child) لمسار الجذر هكذا، لا ابنًا لـ settings هكذا. فكيف يمكننا فعل ذلك؟ لأنّه إذا ذهبنا إلى مجلد settings، ولِنقل أنّنا نُنشئ هنا ملفًا جديدًا، فلنقل
[08:11] password أو ما شابه ذلك، بامتداد tsx.
[08:17] الآن، هذا المسار سيكون بالطبع ابنًا لـ settings. فإذا ذهبنا إلى settings/password، فسَيُصيَّر مسار settings، وسَيُطابَق. عذرًا، أظنّ أنّ لديّ خطأً إملائيًا (typo) هنا في password. لِنُعِد تسمية هذا إلى password، هكذا.
[08:29] إذًا، ماذا لو أردنا أن يكون مسار settings/password هذا غيرَ ابنٍ لـ settings؟ فنحن لسنا مضطرّين إلى امتلاك هذا النص وجهة التنقّل هذه وما إلى ذلك. نحتاج
[08:44] ابنًا لمسار الجذر.
[08:47] ما يمكننا فعله هو أنّنا، بدلًا من وجود هذه هنا، يمكننا إنشاء مجلد جديد، عذرًا، مجلدًا لا ملفًا، وسيُسمّى هذا المجلد، عذرًا، settings ثم شرطة سفلية (underscore)، صحيح.
[09:05] وبامتلاكنا لهذا يمكننا نقل password إلى هذا المجلد، وبهذه الطريقة سَيَكُون عنوان URL لهذا المسار settings/password، وستُهمَل هذه الشرطة السفلية. لكنّه الآن لن يكون
[09:22] ابنًا لهذا مسار settings. وكما تلاحظ، لا نملك ذلك التنقّل، ولا نملك النص الخاص بـ /settings وما إلى ذلك. فإذا تطلّعنا ربّما إلى الشجرة، فsettings/password صار الآن مسارًا بذاته، وليس
[09:38] ابنًا لـ settings.
[09:41] إذًا هكذا يمكننا فعل ذلك، بمجرد إضافة هذه الشرطة السفلية، لمطابقة عنوان URL معيّن من دون الاضطرار إلى أن نكون ابنًا مباشرًا لهذا مسار settings.