الربط والتنقل
يسمح لك موجه Next.js بإجراء انتقالات بين الصفحات من جانب العميل، مشابهًا لتطبيق الصفحة الواحدة (SPA).
يتم توفير مكون React يسمى Link
لتنفيذ هذا الانتقال من جانب العميل.
import Link from 'next/link'
function Home() {
return (
<ul>
<li>
<Link href="/">الصفحة الرئيسية</Link>
</li>
<li>
<Link href="/about">من نحن</Link>
</li>
<li>
<Link href="/blog/hello-world">مقالة المدونة</Link>
</li>
</ul>
)
}
export default Home
يستخدم المثال أعلاه روابط متعددة. كل رابط يربط مسارًا (href
) بصفحة معروفة:
/
→pages/index.js
/about
→pages/about.js
/blog/hello-world
→pages/blog/[slug].js
أي <Link />
في نطاق الرؤية (مبدئيًا أو عن طريق التمرير) سيتم جلبها مسبقًا افتراضيًا (بما في ذلك البيانات المقابلة) للصفحات التي تستخدم التوليد الثابت (Static Generation). يتم جلب البيانات المقابلة لطرق العرض من جانب الخادم (server-rendered) فقط عند النقر على <Link />
.
الربط بمسارات ديناميكية
يمكنك أيضًا استخدام الاستيفاء لإنشاء المسار، وهو مفيد لـ أجزاء المسار الديناميكية (dynamic route segments). على سبيل المثال، لعرض قائمة بالمقالات التي تم تمريرها إلى المكون كخاصية:
import Link from 'next/link'
function Posts({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>
<Link href={`/blog/${encodeURIComponent(post.slug)}`}>
{post.title}
</Link>
</li>
))}
</ul>
)
}
export default Posts
يتم استخدام
encodeURIComponent
في المثال للحفاظ على توافق المسار مع utf-8.
بدلاً من ذلك، باستخدام كائن URL:
import Link from 'next/link'
function Posts({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>
<Link
href={{
pathname: '/blog/[slug]',
query: { slug: post.slug },
}}
>
{post.title}
</Link>
</li>
))}
</ul>
)
}
export default Posts
الآن، بدلاً من استخدام الاستيفاء لإنشاء المسار، نستخدم كائن URL في href
حيث:
pathname
هو اسم الصفحة في دليلpages
. في هذه الحالة/blog/[slug]
.query
هو كائن يحتوي على الجزء الديناميكي. في هذه الحالةslug
.
حقن الموجه (Router)
للوصول إلى كائن الموجه (router
) في مكون React، يمكنك استخدام useRouter
أو withRouter
.
بشكل عام، نوصي باستخدام useRouter
.
التنقل الأمرية (Imperative Routing)
يجب أن يكون next/link
قادرًا على تغطية معظم احتياجاتك للتنقل، ولكن يمكنك أيضًا تنفيذ التنقل من جانب العميل بدونه، راجع توثيق next/router
.
يوضح المثال التالي كيفية تنفيذ التنقل الأساسي بين الصفحات باستخدام useRouter
:
import { useRouter } from 'next/router'
export default function ReadMore() {
const router = useRouter()
return (
<button onClick={() => router.push('/about')}>
انقر هنا لقراءة المزيد
</button>
)
}
التنقل السطحي (Shallow Routing)
أمثلة
يسمح لك التنقل السطحي بتغيير عنوان URL دون إعادة تشغيل طرق جلب البيانات مرة أخرى، وهذا يشمل getServerSideProps
، وgetStaticProps
، وgetInitialProps
.
ستتلقى pathname
و query
المحدثين عبر كائن الموجه (router
) (الذي يتم إضافته بواسطة useRouter
أو withRouter
)، دون فقدان الحالة.
لتمكين التنقل السطحي، اضبط خيار shallow
على true
. ضع في اعتبارك المثال التالي:
import { useEffect } from 'react'
import { useRouter } from 'next/router'
// عنوان URL الحالي هو '/'
function Page() {
const router = useRouter()
useEffect(() => {
// دائمًا قم بالتنقل بعد التصيير الأول
router.push('/?counter=10', undefined, { shallow: true })
}, [])
useEffect(() => {
// لقد تغير العداد!
}, [router.query.counter])
}
export default Page
سيتم تحديث عنوان URL إلى /?counter=10
ولن يتم استبدال الصفحة، فقط حالة المسار تتغير.
يمكنك أيضًا مراقبة تغييرات عنوان URL عبر componentDidUpdate
كما هو موضح أدناه:
componentDidUpdate(prevProps) {
const { pathname, query } = this.props.router
// تحقق من تغير الخصائص لتجنب حلقة لا نهائية
if (query.counter !== prevProps.router.query.counter) {
// جلب البيانات بناءً على الاستعلام الجديد
}
}
محاذير
يعمل التنقل السطحي فقط لتغييرات عنوان URL في الصفحة الحالية. على سبيل المثال، لنفترض أن لدينا صفحة أخرى تسمى pages/about.js
، وقمت بتنفيذ هذا:
router.push('/?counter=10', '/about?counter=10', { shallow: true })
نظرًا لأن هذه صفحة جديدة، سيتم تفريغ الصفحة الحالية، وتحميل الصفحة الجديدة وانتظار جلب البيانات حتى لو طلبنا تنفيذ تنقل سطحي.
عند استخدام التنقل السطحي مع middleware، فلن يضمن أن الصفحة الجديدة تطابق الصفحة الحالية كما كان يحدث سابقًا بدون middleware. هذا بسبب أن middleware يمكنه إعادة الكتابة ديناميكيًا ولا يمكن التحقق منه من جانب العميل دون جلب بيانات يتم تخطيه مع التنقل السطحي، لذا يجب دائمًا معاملة تغيير المسار السطحي على أنه سطحي.