الربط والتنقل
هناك أربع طرق للتنقل بين المسارات في Next.js:
- استخدام مكون
<Link>
- استخدام خطاف
useRouter
(مكونات العميل) - استخدام دالة
redirect
(مكونات الخادم) - استخدام واجهة History الأصلية
ستغطي هذه الصفحة كيفية استخدام كل من هذه الخيارات، والتعمق في كيفية عمل التنقل.
مكون <Link>
<Link>
هو مكون مدمج يمتد من وسم HTML <a>
لتوفير الجلب المسبق والتنقل بين المسارات من جانب العميل. وهو الطريقة الأساسية والموصى بها للتنقل بين المسارات في Next.js.
يمكنك استخدامه عن طريق استيراده من next/link
، وتمرير خاصية href
إلى المكون:
import Link from 'next/link'
export default function Page() {
return <Link href="/dashboard">لوحة التحكم</Link>
}
import Link from 'next/link'
export default function Page() {
return <Link href="/dashboard">لوحة التحكم</Link>
}
هناك خصائص اختيارية أخرى يمكنك تمريرها إلى <Link>
. راجع مرجع API للمزيد.
أمثلة
الربط إلى الأجزاء الديناميكية
عند الربط إلى الأجزاء الديناميكية، يمكنك استخدام القوالب الحرفية والاستيفاء لإنشاء قائمة من الروابط. على سبيل المثال، لإنشاء قائمة من منشورات المدونة:
import Link from 'next/link'
export default function PostList({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>
<Link href={`/blog/${post.slug}`}>{post.title}</Link>
</li>
))}
</ul>
)
}
التحقق من الروابط النشطة
يمكنك استخدام usePathname()
لتحديد ما إذا كان الرابط نشطًا. على سبيل المثال، لإضافة فئة إلى الرابط النشط، يمكنك التحقق مما إذا كان pathname
الحالي يتطابق مع href
الرابط:
'use client'
import { usePathname } from 'next/navigation'
import Link from 'next/link'
export function Links() {
const pathname = usePathname()
return (
<nav>
<ul>
<li>
<Link className={`link ${pathname === '/' ? 'active' : ''}`} href="/">
الرئيسية
</Link>
</li>
<li>
<Link
className={`link ${pathname === '/about' ? 'active' : ''}`}
href="/about"
>
حول
</Link>
</li>
</ul>
</nav>
)
}
'use client'
import { usePathname } from 'next/navigation'
import Link from 'next/link'
export function Links() {
const pathname = usePathname()
return (
<nav>
<ul>
<li>
<Link className={`link ${pathname === '/' ? 'active' : ''}`} href="/">
الرئيسية
</Link>
</li>
<li>
<Link
className={`link ${pathname === '/about' ? 'active' : ''}`}
href="/about"
>
حول
</Link>
</li>
</ul>
</nav>
)
}
التمرير إلى id
السلوك الافتراضي لموجه تطبيق Next.js هو التمرير إلى أعلى مسار جديد أو الحفاظ على موضع التمرير للتنقل للخلف وللأمام.
إذا كنت ترغب في التمرير إلى id
معين عند التنقل، يمكنك إضافة رابط #
إلى عنوان URL الخاص بك أو تمرير رابط #
إلى خاصية href
. هذا ممكن لأن <Link>
يتم عرضه كوسم <a>
.
<Link href="/dashboard#settings">الإعدادات</Link>
// الناتج
<a href="/dashboard#settings">الإعدادات</a>
جيد أن تعرف:
- سيقوم Next.js بالتمرير إلى الصفحة إذا لم تكن مرئية في نافذة العرض عند التنقل.
تعطيل استعادة التمرير
السلوك الافتراضي لموجه تطبيق Next.js هو التمرير إلى أعلى مسار جديد أو الحفاظ على موضع التمرير للتنقل للخلف وللأمام. إذا كنت ترغب في تعطيل هذا السلوك، يمكنك تمرير scroll={false}
إلى مكون <Link>
، أو scroll: false
إلى router.push()
أو router.replace()
.
// next/link
<Link href="/dashboard" scroll={false}>
لوحة التحكم
</Link>
// useRouter
import { useRouter } from 'next/navigation'
const router = useRouter()
router.push('/dashboard', { scroll: false })
خطاف useRouter()
يسمح لك خطاف useRouter
بتغيير المسارات برمجيًا من مكونات العميل.
'use client'
import { useRouter } from 'next/navigation'
export default function Page() {
const router = useRouter()
return (
<button type="button" onClick={() => router.push('/dashboard')}>
لوحة التحكم
</button>
)
}
للحصول على قائمة كاملة بطرق useRouter
، راجع مرجع API.
توصية: استخدم مكون
<Link>
للتنقل بين المسارات ما لم يكن لديك متطلب محدد لاستخدامuseRouter
.
دالة redirect
بالنسبة لـ مكونات الخادم، استخدم دالة redirect
بدلاً من ذلك.
import { redirect } from 'next/navigation'
async function fetchTeam(id: string) {
const res = await fetch('https://...')
if (!res.ok) return undefined
return res.json()
}
export default async function Profile({ params }: { params: { id: string } }) {
const team = await fetchTeam(params.id)
if (!team) {
redirect('/login')
}
// ...
}
import { redirect } from 'next/navigation'
async function fetchTeam(id) {
const res = await fetch('https://...')
if (!res.ok) return undefined
return res.json()
}
export default async function Profile({ params }) {
const team = await fetchTeam(params.id)
if (!team) {
redirect('/login')
}
// ...
}
جيد أن تعرف:
- تُرجع
redirect
رمز حالة 307 (إعادة توجيه مؤقت) افتراضيًا. عند استخدامها في إجراء خادم، تُرجع 303 (انظر الآخر)، والذي يُستخدم عادةً لإعادة التوجيه إلى صفحة نجاح نتيجة لطلب POST.- تطرح
redirect
خطأ داخليًا لذا يجب استدعاؤها خارج كتلtry/catch
.- يمكن استدعاء
redirect
في مكونات العميل أثناء عملية العرض ولكن ليس في معالجات الأحداث. يمكنك استخدام خطافuseRouter
بدلاً من ذلك.- تقبل
redirect
أيضًا عناوين URL المطلقة ويمكن استخدامها لإعادة التوجيه إلى روابط خارجية.- إذا كنت ترغب في إعادة التوجيه قبل عملية العرض، استخدم
next.config.js
أو البرنامج الوسيط.
راجع مرجع API لـ redirect
للمزيد من المعلومات.
استخدام واجهة History الأصلية
يسمح لك Next.js باستخدام الطرق الأصلية window.history.pushState
و window.history.replaceState
لتحديث سجل المتصفح دون إعادة تحميل الصفحة.
تتكامل استدعاءات pushState
و replaceState
مع موجه Next.js، مما يسمح لك بالمزامنة مع usePathname
و useSearchParams
.
window.history.pushState
استخدمها لإضافة إدخال جديد إلى سجل المتصفح. يمكن للمستخدم التنقل للخلف إلى الحالة السابقة. على سبيل المثال، لفرز قائمة من المنتجات:
'use client'
import { useSearchParams } from 'next/navigation'
export default function SortProducts() {
const searchParams = useSearchParams()
function updateSorting(sortOrder: string) {
const params = new URLSearchParams(searchParams.toString())
params.set('sort', sortOrder)
window.history.pushState(null, '', `?${params.toString()}`)
}
return (
<>
<button onClick={() => updateSorting('asc')}>فرز تصاعدي</button>
<button onClick={() => updateSorting('desc')}>فرز تنازلي</button>
</>
)
}
'use client'
import { useSearchParams } from 'next/navigation'
export default function SortProducts() {
const searchParams = useSearchParams()
function updateSorting(sortOrder) {
const params = new URLSearchParams(searchParams.toString())
params.set('sort', sortOrder)
window.history.pushState(null, '', `?${params.toString()}`)
}
return (
<>
<button onClick={() => updateSorting('asc')}>فرز تصاعدي</button>
<button onClick={() => updateSorting('desc')}>فرز تنازلي</button>
</>
)
}
window.history.replaceState
استخدمها لاستبدال الإدخال الحالي في سجل المتصفح. لا يمكن للمستخدم التنقل للخلف إلى الحالة السابقة. على سبيل المثال، لتبديل لغة التطبيق:
'use client'
import { usePathname } from 'next/navigation'
export function LocaleSwitcher() {
const pathname = usePathname()
function switchLocale(locale: string) {
// مثال: '/en/about' أو '/fr/contact'
const newPath = `/${locale}${pathname}`
window.history.replaceState(null, '', newPath)
}
return (
<>
<button onClick={() => switchLocale('en')}>الإنجليزية</button>
<button onClick={() => switchLocale('fr')}>الفرنسية</button>
</>
)
}
'use client'
import { usePathname } from 'next/navigation'
export function LocaleSwitcher() {
const pathname = usePathname()
function switchLocale(locale) {
// مثال: '/en/about' أو '/fr/contact'
const newPath = `/${locale}${pathname}`
window.history.replaceState(null, '', newPath)
}
return (
<>
<button onClick={() => switchLocale('en')}>الإنجليزية</button>
<button onClick={() => switchLocale('fr')}>الفرنسية</button>
</>
)
}
كيفية عمل التوجيه والتنقل
يستخدم موجه التطبيق نهجًا هجينًا للتوجيه والتنقل. على الخادم، يتم تقسيم الكود تلقائيًا حسب أجزاء المسار. وعلى العميل، يقوم Next.js بجلب مسبق وتخزين مؤقت لأجزاء المسار. هذا يعني أنه عندما ينتقل المستخدم إلى مسار جديد، لا يقوم المتصفح بإعادة تحميل الصفحة، ويعاد عرض أجزاء المسار التي تتغير فقط - مما يحسن تجربة التنقل والأداء.
1. تقسيم الكود
يسمح لك تقسيم الكود بتقسيم كود التطبيق إلى حزم أصغر ليتم تنزيلها وتنفيذها بواسطة المتصفح. هذا يقلل من كمية البيانات المنقولة ووقت التنفيذ لكل طلب، مما يؤدي إلى تحسين الأداء.
تسمح لك مكونات الخادم بتقسيم كود التطبيق تلقائيًا حسب أجزاء المسار. هذا يعني أنه يتم تحميل الكود المطلوب للمسار الحالي فقط عند التنقل.
2. الجلب المسبق
الجلب المسبق هو طريقة لتحميل مسار مسبقًا في الخلفية قبل أن يزوره المستخدم.
هناك طريقتان لجلب المسارات مسبقًا في Next.js:
- مكون
<Link>
: يتم جلب المسارات مسبقًا تلقائيًا عندما تصبح مرئية في نافذة عرض المستخدم. يحدث الجلب المسبق عند تحميل الصفحة لأول مرة أو عندما تصبح مرئية عن طريق التمرير. router.prefetch()
: يمكن استخدام خطافuseRouter
لجلب المسارات مسبقًا برمجيًا.
يختلف سلوك الجلب المسبق الافتراضي لـ <Link>
(أي عندما تكون الخاصية prefetch
غير محددة أو مضبوطة على null
) اعتمادًا على استخدامك لـ loading.js
. يتم جلب التخطيط المشترك فقط، وصولاً إلى "شجرة" المكونات المعروضة حتى ملف loading.js
الأول، وتخزينه مؤقتًا لمدة 30s
. هذا يقلل من تكلفة جلب مسار ديناميكي كامل، ويعني أنه يمكنك عرض حالة تحميل فورية لردود فعل مرئية أفضل للمستخدمين.
يمكنك تعطيل الجلب المسبق عن طريق ضبط الخاصية prefetch
على false
. بدلاً من ذلك، يمكنك جلب بيانات الصفحة الكاملة بما يتجاوز حدود التحميل عن طريق ضبط الخاصية prefetch
على true
.
راجع مرجع API لـ <Link>
للمزيد من المعلومات.
جيد أن تعرف:
- لا يتم تمكين الجلب المسبق في وضع التطوير، فقط في الإنتاج.
3. التخزين المؤقت
يحتوي Next.js على تخزين مؤقت من جانب العميل في الذاكرة يسمى تخزين الموجه المؤقت. أثناء تنقل المستخدمين في التطبيق، يتم تخزين حمولة مكون خادم React لأجزاء المسار المسبقة الجلب والمسارات التي تمت زيارتها في التخزين المؤقت.
هذا يعني عند التنقل، يتم إعادة استخدام التخزين المؤقت قدر الإمكان، بدلاً من إجراء طلب جديد إلى الخادم - مما يحسن الأداء عن طريق تقليل عدد الطلبات والبيانات المنقولة.
تعرف على المزيد حول كيفية عمل تخزين الموجه المؤقت وكيفية تكوينه.
4. العرض الجزئي
يعني العرض الجزئي أنه يتم إعادة عرض أجزاء المسار التي تتغير فقط عند التنقل على العميل، ويتم الحفاظ على أي أجزاء مشتركة.
على سبيل المثال، عند التنقل بين مسارين شقيقين، /dashboard/settings
و /dashboard/analytics
، سيتم عرض صفحات settings
و analytics
، وسيتم الحفاظ على تخطيط dashboard
المشترك.

بدون العرض الجزئي، سيؤدي كل تنقل إلى إعادة عرض الصفحة بالكامل على العميل. يؤدي عرض الجزء الذي يتغير فقط إلى تقليل كمية البيانات المنقولة ووقت التنفيذ، مما يؤدي إلى تحسين الأداء.
5. التنقل الناعم
يقوم المتصفحات بتنفيذ "تنقل صعب" عند التنقل بين الصفحات. يمكّن موجه تطبيق Next.js "التنقل الناعم" بين الصفحات، مما يضمن إعادة عرض أجزاء المسار التي تغيرت فقط (العرض الجزئي). هذا يمكّن من الحفاظ على حالة React للعميل أثناء التنقل.
6. التنقل للخلف وللأمام
افتراضيًا، سوف يحافظ Next.js على موضع التمرير للتنقل للخلف وللأمام، ويعيد استخدام أجزاء المسار في تخزين الموجه المؤقت.
7. التوجيه بين pages/
و app/
عند الترحيل التدريجي من pages/
إلى app/
، سيتعامل موجه Next.js تلقائيًا مع التنقل الصعب بين الاثنين. للكشف عن الانتقالات من pages/
إلى app/
، هناك مرشح لموجه العميل يستخدم التحقق الاحتمالي من مسارات التطبيق، مما قد يؤدي أحيانًا إلى نتائج إيجابية خاطئة. افتراضيًا، يجب أن تكون مثل هذه الحالات نادرة جدًا، حيث نقوم بتكوين احتمالية النتيجة الإيجابية الخاطئة لتكون 0.01%. يمكن تخصيص هذه الاحتمالية عبر خيار experimental.clientRouterFilterAllowedRate
في next.config.js
. من المهم ملاحظة أن خفض معدل النتائج الإيجابية الخاطئة سيزيد من حجم المرشح المُنشأ في حزمة العميل.
بدلاً من ذلك، إذا كنت تفضل تعطيل هذه المعالجة تمامًا وإدارة التوجيه بين pages/
و app/
يدويًا، يمكنك ضبط experimental.clientRouterFilter
على false في next.config.js
. عند تعطيل هذه الميزة، لن يتم التنقل إلى أي مسارات ديناميكية في الصفحات التي تتداخل مع مسارات التطبيق بشكل صحيح افتراضيًا.