ماذا سنتعلم اليوم؟
سنتعلم كيفية بناء لوحات تحكم معقدة باستخدام مفهوم التوجيه المتداخل (Nested Routing) في Next.js App Router، مما يسمح لنا بإنشاء تخطيطات واجهة مستخدم متعددة المستويات وقابلة للتوسع.
مقدمة إلى التوجيه المتداخل
التوجيه المتداخل في Next.js App Router يسمح لك بإنشاء مسارات (routes) داخل مسارات أخرى. هذا يعني أن جزءًا من واجهة المستخدم (UI) يمكن أن يظل ثابتًا بينما يتغير جزء آخر بناءً على المسار الفرعي. إنه مثالي للوحات التحكم، حيث يكون لديك شريط جانبي ثابت (sidebar) أو رأس (header) ومساحة محتوى تتغير.
الخطوة 1: إعداد المسارات الأساسية للوحة التحكم
سنبدأ بإنشاء مجلد dashboard داخل مجلد app. داخل هذا المجلد، سنقوم بإنشاء ملف layout.tsx لتعريف التخطيط المشترك لجميع المسارات داخل لوحة التحكم، وملف page.tsx ليكون الصفحة الرئيسية للوحة التحكم.
app/dashboard/layout.tsx
هذا الملف سيحدد التخطيط العام للوحة التحكم، بما في ذلك شريط التنقل الجانبي.
import Link from 'next/link';
export default function DashboardLayout({
children, // خاصية children ستعرض المحتوى الخاص بالمسارات المتداخلة هنا
}: {
children: React.ReactNode;
}) {
return (
<div className="flex min-h-screen bg-gray-50">
{/* شريط التنقل الجانبي */}
<nav className="w-64 bg-gray-800 text-white p-4 shadow-lg">
<h2 className="text-3xl font-extrabold mb-8 text-indigo-400">لوحة التحكم</h2>
<ul>
<li className="mb-3">
<Link href="/dashboard" className="block p-3 rounded-md transition-colors duration-200 hover:bg-gray-700 hover:text-indigo-300">
الرئيسية
</Link>
</li>
<li className="mb-3">
<Link href="/dashboard/settings" className="block p-3 rounded-md transition-colors duration-200 hover:bg-gray-700 hover:text-indigo-300">
الإعدادات
</Link>
</li>
<li className="mb-3">
<Link href="/dashboard/analytics" className="block p-3 rounded-md transition-colors duration-200 hover:bg-gray-700 hover:text-indigo-300">
التحليلات
</Link>
</li>
</ul>
</nav>
{/* منطقة المحتوى الرئيسية */}
<main className="flex-1 p-10">
{children} {/* هنا يتم عرض محتوى المسار المتداخل الحالي */}
</main>
</div>
);
}
app/dashboard/page.tsx
هذه هي الصفحة الافتراضية التي ستعرض عند زيارة /dashboard.
export default function DashboardPage() {
return (
<div className="bg-white p-8 rounded-lg shadow-md">
<h1 className="text-4xl font-bold mb-4 text-gray-800">مرحباً بك في لوحة التحكم الرئيسية!</h1>
<p className="text-lg text-gray-600">استخدم شريط التنقل الجانبي لاستكشاف الأقسام المختلفة.</p>
</div>
);
}
الخطوة 2: إضافة مسارات متداخلة للصفحات الفرعية
الآن سنقوم بإنشاء صفحات فرعية داخل لوحة التحكم. هذه الصفحات ستعرض داخل children الخاص بـ DashboardLayout.
app/dashboard/settings/page.tsx
صفحة الإعدادات لـ /dashboard/settings.
export default function SettingsPage() {
return (
<div className="bg-white p-8 rounded-lg shadow-md">
<h1 className="text-4xl font-bold mb-4 text-gray-800">صفحة الإعدادات</h1>
<p className="text-lg text-gray-600">هنا يمكنك إدارة إعدادات التطبيق الخاصة بك.</p>
{/* يمكنك إضافة المزيد من مكونات الإعدادات هنا */}
</div>
);
}
app/dashboard/analytics/page.tsx
صفحة التحليلات لـ /dashboard/analytics.
export default function AnalyticsPage() {
return (
<div className="bg-white p-8 rounded-lg shadow-md">
<h1 className="text-4xl font-bold mb-4 text-gray-800">صفحة التحليلات</h1>
<p className="text-lg text-gray-600">عرض بيانات التحليلات والرسوم البيانية هنا.</p>
{/* يمكنك إضافة المزيد من مكونات التحليلات هنا */}
</div>
);
}
الخطوة 3: التنقل بين المسارات المتداخلة باستخدام <Link>
لقد قمنا بالفعل بدمج روابط التنقل في app/dashboard/layout.tsx. يستخدم مكون <Link> من next/link للانتقال بين المسارات دون إعادة تحميل الصفحة بالكامل، مما يوفر تجربة مستخدم سلسة. عندما تنقر على أحد الروابط، سيتم تحديث المحتوى داخل منطقة <main> بينما يظل شريط التنقل الجانبي ثابتًا.
ميزة
<Link>هي أنها تقوم بجلب بيانات المسار المستهدف مسبقًا (prefetches) في الخلفية، مما يجعل التنقل فوريًا تقريبًا عند النقر.
الكود النهائي الكامل
للحصول على هذا المثال يعمل، تأكد من أن لديك مشروع Next.js جديد (يمكنك إنشاؤه باستخدام npx create-next-app@latest my-dashboard-app واختيار App Router). ثم قم بإنشاء الملفات التالية ووضع الأكواد بها.
app/dashboard/layout.tsx
import Link from 'next/link';
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="flex min-h-screen bg-gray-50">
<nav className="w-64 bg-gray-800 text-white p-4 shadow-lg">
<h2 className="text-3xl font-extrabold mb-8 text-indigo-400">لوحة التحكم</h2>
<ul>
<li className="mb-3">
<Link href="/dashboard" className="block p-3 rounded-md transition-colors duration-200 hover:bg-gray-700 hover:text-indigo-300">
الرئيسية
</Link>
</li>
<li className="mb-3">
<Link href="/dashboard/settings" className="block p-3 rounded-md transition-colors duration-200 hover:bg-gray-700 hover:text-indigo-300">
الإعدادات
</Link>
</li>
<li className="mb-3">
<Link href="/dashboard/analytics" className="block p-3 rounded-md transition-colors duration-200 hover:bg-gray-700 hover:text-indigo-300">
التحليلات
</Link>
</li>
</ul>
</nav>
<main className="flex-1 p-10">
{children}
</main>
</div>
);
}
app/dashboard/page.tsx
export default function DashboardPage() {
return (
<div className="bg-white p-8 rounded-lg shadow-md">
<h1 className="text-4xl font-bold mb-4 text-gray-800">مرحباً بك في لوحة التحكم الرئيسية!</h1>
<p className="text-lg text-gray-600">استخدم شريط التنقل الجانبي لاستكشاف الأقسام المختلفة.</p>
</div>
);
}
app/dashboard/settings/page.tsx
export default function SettingsPage() {
return (
<div className="bg-white p-8 rounded-lg shadow-md">
<h1 className="text-4xl font-bold mb-4 text-gray-800">صفحة الإعدادات</h1>
<p className="text-lg text-gray-600">هنا يمكنك إدارة إعدادات التطبيق الخاصة بك.</p>
</div>
);
}
app/dashboard/analytics/page.tsx
export default function AnalyticsPage() {
return (
<div className="bg-white p-8 rounded-lg shadow-md">
<h1 className="text-4xl font-bold mb-4 text-gray-800">صفحة التحليلات</h1>
<p className="text-lg text-gray-600">عرض بيانات التحليلات والرسوم البيانية هنا.</p>
</div>
);
}
النتيجة المتوقعة
عند تشغيل التطبيق وزيارة المسار /dashboard، ستشاهد شريط تنقل جانبي ثابت يحتوي على روابط لـ "الرئيسية" و "الإعدادات" و "التحليلات". في المنطقة الرئيسية على اليمين، سيتم عرض المحتوى الخاص بالصفحة الحالية (مثل "مرحباً بك في لوحة التحكم الرئيسية!"). عند النقر على "الإعدادات"، سيظل الشريط الجانبي كما هو، بينما يتغير المحتوى الرئيسي ليظهر "صفحة الإعدادات". نفس الشيء سيحدث عند النقر على "التحليلات". هذا يوضح كيف يمكنك بناء واجهات مستخدم معقدة ومنظمة باستخدام التوجيه المتداخل.