الفرق بين المراجعتين لصفحة: «Next.js/next link»

من موسوعة حسوب
لا ملخص تعديل
طلا ملخص تعديل
 
(5 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:الواجهة البرمجية للمكوّن <code>next/link</code> في Next.js}}</noinclude>
<noinclude>{{DISPLAYTITLE:الواجهة البرمجية للمكوّن <code>next/link</code> في Next.js}}</noinclude>
<blockquote>ننصحك قبل قراءة المقال بالاطلاع على [[Next.js/Routing|التوجّه في Next.js]] أولًا</blockquote>بالإمكان تفعيل التنقل بين الصفحات أو الوجهات في جانب العميل عبر المكوّن <code>Link</code> الذي تصدّره المكتبة <code>next/link</code>.
<blockquote>ننصحك قبل قراءة المقال بالاطلاع على [[Next.js/Routing|التوجيه في Next.js]] أولًا.</blockquote>بإمكانك تفعيل التنقل بين الصفحات أو الوجهات في جانب العميل عبر المكوّن <code>Link</code> المستورد عبر <code>next/link</code>.


لنفترض وجود الملفات التالية في المجلد <code>pages</code>:
لنفترض وجود الملفات التالية في المجلد <code>pages</code>:
سطر 9: سطر 9:


يمكننا الحصول على رابط إلى كل صفحة من هذه الصفحات كالتالي:<syntaxhighlight lang="javascript">
يمكننا الحصول على رابط إلى كل صفحة من هذه الصفحات كالتالي:<syntaxhighlight lang="javascript">
# الواجهة البرمجية للمكوّن `next/link` في Next.js
import Link from 'next/link'


> ننصحك قبل قراءة المقال بالاطلاع على [التوجّه في Next.js](Next.js/Routing) أولًا
function Home() {
  return (
    <ul>
      <li>
        <Link href="/">Home</Link>
      </li>
      <li>
        <Link href="/about">About Us</Link>
      </li>
      <li>
        <Link href="/blog/hello-world">Blog Post</Link>
      </li>
    </ul>
  )
}


بالإمكان تفعيل التنقل بين الصفحات أو الوجهات في جانب العميل عبر المكوّن `Link` الذي تصدّره المكتبة `next/link`.
export default Home
 
</syntaxhighlight>
لنفترض وجود الملفات التالية في المجلد `pages`:


- `pages/index.js`
يقبل المكوّن <code>Link</code> الخاصيات التالية:
- `pages/about.js`
- `pages/blog/[slug].js`
 
يمكننا الحصول على رابط إلى كل صفحة ون هذه الصفحات كالتالي:
</syntaxhighlight>يقبل المكوّن <code>Link</code> الخاصيات التالية:


* <code>href</code>: المسار أو عنوان URL الذي سننتقل إليه. وهذه الخاصية هي الوحيدة التي نحتاجها، كما يمكن أن تكون كائنًا (كائن URL).
* <code>href</code>: المسار أو عنوان URL الذي سننتقل إليه. وهذه الخاصية هي الوحيدة التي نحتاجها، كما يمكن أن تكون كائنًا (كائن URL).
* <code>as</code>: منسّق اختياري للمسار الذي سيُعرض في شريط عناوين المتصفح. استُخدم هذا المعامل سابقًا للتوجه الديناميكي ما قبل الإصدار 9.5.3.
* <code>as</code>: منسّق اختياري للمسار الذي سيُعرض في شريط عناوين المتصفح. استُخدم هذا المعامل سابقًا للتوجه الديناميكي ما قبل الإصدار 9.5.3. '''ملاحظة''': إن اختلف المسار هذا المعطى عن المسار المعطى في href فإن سلوك <code>href</code>/<code>as</code> القديم المستخدم في ذلك الإصدار هو الذي سيُستخدم، فارجع إلى [https://nextjs.org/docs/tag/v9.5.2/api-reference/next/link#dynamic-routes التوثيق القديم].
* legacyBehavior: يغير السلوك ويعود للسلوك القديم الذي يتطلب وجود عنصر <code><a></code> ابن، ويأخذ القيمة الافتراضية <code>false</code>.
* <code>passHref</code>: يجبر المكوّن <code>Link</code> على إرسال الخاصية <code>href</code> إلى أبناءه، ويأخذ القيمة الافتراضية <code>false</code>.
* <code>passHref</code>: يجبر المكوّن <code>Link</code> على إرسال الخاصية <code>href</code> إلى أبناءه، ويأخذ القيمة الافتراضية <code>false</code>.
* <code>prefetch</code>: يحضر الصفحة مسبقًا وراء الستار، ويأخذ القيمة الافتراضية <code>true</code>. كما سيُعاد تحميل أي مكوّن <code></ Link></code> ظاهر في نافذة العرض (في البداية أو عند التمرير). يمكن تعطيل هذه الخاصية بتمرير القيمة <code>prefetch={false}</code>. وعندما تأخذ الخاصية <code>prefetch</code> القيمة <code>false</code>، ستستمر عملية الإحضار المسبق عند مرور مؤشر الفأرة فوق العنصر hovering. ستعيد الصفحات التي تستخدم التوليد [[Next.js/data fetching#.D8.A7.D9.84.D8.AA.D9.88.D9.84.D9.8A.D8.AF%20.D8.A7.D9.84.D8.B3.D8.A7.D9.83.D9.86%20.D9.84.D9.84.D8.B5.D9.81.D8.AD.D8.A7.D8.AA%20.D9.81.D9.8A%20Next.js%20.D8.A8.D8.A7.D8.B3.D8.AA.D8.AE.D8.AF.D8.A7.D9.85%20.D8.A7.D9.84.D8.AF.D8.A7.D9.84.D8.A9%20getStaticProps|الساكن توليد]] ملفات <code>JSON</code> مع البيانات لتسريع عملية الانتقال بين الصفحات. تُفعّل الخاصية <code>prefetch</code> في مرحلة الإنتاج فقط.
* <code>prefetch</code>: يحضر الصفحة مسبقًا وراء الستار، ويأخذ القيمة الافتراضية <code>true</code>. كما سيُعاد تحميل أي مكوّن <code></ Link></code> ظاهر في نافذة العرض (في البداية أو عند التمرير). يمكن تعطيل هذه الخاصية بتمرير القيمة <code>prefetch={false}</code>. وعندما تأخذ الخاصية <code>prefetch</code> القيمة <code>false</code>، ستستمر عملية الإحضار المسبق عند مرور مؤشر الفأرة فوق العنصر hovering. ستعيد الصفحات التي تستخدم التوليد [[Next.js/data fetching#.D8.A7.D9.84.D8.AA.D9.88.D9.84.D9.8A.D8.AF%20.D8.A7.D9.84.D8.B3.D8.A7.D9.83.D9.86%20.D9.84.D9.84.D8.B5.D9.81.D8.AD.D8.A7.D8.AA%20.D9.81.D9.8A%20Next.js%20.D8.A8.D8.A7.D8.B3.D8.AA.D8.AE.D8.AF.D8.A7.D9.85%20.D8.A7.D9.84.D8.AF.D8.A7.D9.84.D8.A9%20getStaticProps|الساكن توليد]] ملفات <code>JSON</code> مع البيانات لتسريع عملية الانتقال بين الصفحات. تُفعّل الخاصية <code>prefetch</code> في مرحلة الإنتاج فقط.
* <code>replace</code>: يستبدل حالة سجل العناوين history بدلًا من إضافة عنوان url جديد إلى المكدّس، ويأخذ القيمة الافتراضية <code>false</code>.
* <code>replace</code>: يستبدل حالة سجل العناوين history بدلًا من إضافة عنوان url جديد إلى المكدّس، ويأخذ القيمة الافتراضية <code>false</code>.
* <code>scroll</code>: يتحكم بالتمرير إلى أعلى الصفحة بعد الانتقال، وقيمته الافتراضية <code>true</code>.
* <code>scroll</code>: يتحكم بالتمرير إلى أعلى الصفحة بعد الانتقال، وقيمته الافتراضية <code>true</code>.
* [[Next.js/Routing|<code>shallow</code>]]: يُحدّث مسار الصفحة الحالية دون تنفيذ الدوال [[Next.js/data fetching|<code>getStaticProps</code>]] أو <code>getServerSideProps</code> أو <code>getInitialProps</code>، وقيمته الافتراضية <code>false</code>.  
* [[Next.js/Routing|<code>shallow</code>]]: يُحدّث مسار الصفحة الحالية دون تنفيذ الدوال <code>getStaticProps</code> أو <code>getServerSideProps</code> أو <code>getInitialProps</code>، وقيمته الافتراضية <code>false</code>.
* <code>locale</code>: يُستخدم الإعداد المحلي المُفعَّل تلقائيًا. كما يمكنك استخدامها لتغيير هذا الإعداد. عندما تأخذ الخاصية القيمة <code>false</code> تُعطّل الخاصية <code>href</code> استخدام الإعداد المحلي افتراضيًا.
* <code>locale</code>: يُستخدم الإعداد المحلي المُفعَّل تلقائيًا. كما يمكنك استخدامها لتغيير هذا الإعداد. عندما تأخذ الخاصية القيمة <code>false</code> يجب أن تحدد الخاصية <code>href</code> الإعداد المحلي بما أن السلوك الافتراضي قد تعطل آنذاك.


== حالة وجود أجزاء ديناميكية في الوجهة ==
== حالة وجود أجزاء ديناميكية في الوجهة ==
سطر 45: سطر 54:
         <li key={post.id}>
         <li key={post.id}>
           <Link href={`/blog/${encodeURIComponent(post.slug)}`}>
           <Link href={`/blog/${encodeURIComponent(post.slug)}`}>
             <a>{post.title}</a>
             {post.title}
           </Link>
           </Link>
         </li>
         </li>
سطر 56: سطر 65:
</syntaxhighlight>
</syntaxhighlight>


== حالة وجود مكوّن ابن مخصص للمكون <code>link</code> مغلف بالعنصر <code><a></code> ==
== حالة وجود مكون <code><a></code> ابن مخصص للمكون <code>link</code> ==
لا بد في هذه الحالة من إضافة الخاصية <code>passHref</code> إلى المكوّن <code>link</code>، وهذا ضروري إن كنت تستخدم مكتبات مثل [https://styled-components.com/ styled-components]. لن يمتلك العنصر <code><a></code> دون أن تفعل ذلك السمة <code>href</code>، الأمر الذي يسيء إلى شمولية موقعك وقد يؤثر على نتيجة البحث SEO. وفي حال استخدمت المدقق [[Next.js/eslint|ESLint]]، تأكد من استخدام القاعدة <code>next/link-passhref</code> للتأكد من الاستخدام الصحيح للخاصية <code>passHref</code>:<syntaxhighlight lang="javascript">
إليك المثال التالي الذي يمثل هذه الحالة:<syntaxhighlight lang="javascript">
import Link from 'next/link'
 
function Legacy() {
  return (
    <Link href="/about" legacyBehavior>
      <a>About Us</a>
    </Link>
  )
}
 
export default Legacy
</syntaxhighlight>
 
== حالة وجود مكون ابن مخصص للمكون <code>link</code> مغلف بالعنصر <code><a></code> ==
لا بد في هذه الحالة من إضافة الخاصية <code>passHref</code> إلى المكوّن <code>link</code>، وهذا ضروري إن كنت تستخدم مكتبات مثل [https://styled-components.com/ styled-components]. لن يمتلك العنصر <code><a></code> دون أن تفعل ذلك السمة <code>href</code>، الأمر الذي يسيء إلى سهولة وصول موقعك وقد يؤثر على نتيجة البحث SEO. وفي حال استخدمت المدقق [[Next.js/eslint|ESLint]]، تأكد من استخدام القاعدة <code>next/link-passhref</code> للتأكد من الاستخدام الصحيح للخاصية <code>passHref</code>:<syntaxhighlight lang="javascript">
import Link from 'next/link'
import Link from 'next/link'
import styled from 'styled-components'
import styled from 'styled-components'
سطر 68: سطر 92:
   //Link إلى الرابط href لا بد من إضافة  
   //Link إلى الرابط href لا بد من إضافة  
   return (
   return (
     <Link href={href} passHref>
     <Link href={href} passHref legacyBehavior>
       <RedLink>{name}</RedLink>
       <RedLink>{name}</RedLink>
     </Link>
     </Link>
سطر 77: سطر 101:
</syntaxhighlight>
</syntaxhighlight>


* لا بد أيضًا من استخدام الخاصية <code>passHref</code> إن كنت ستعمل مع الميزة <code>jsx jsx@</code> العائدة لمكتبة التنسيق emotion حتى لو استخدمت <code><a></code> مباشرة.
* لا بد أيضًا من استخدام الخاصية <code>passHref</code> إن كنت ستعمل مع الميزة <code>jsx jsx@</code> العائدة لمكتبة التنسيق [https://emotion.sh/ emotion] حتى لو استخدمت <code><a></code> مباشرة.
* يجب أن يدعم المكوّن الخاصية <code>onClick</code> كي يقع حدث التنقل بالطريقة الصحيحة.
* يجب أن يدعم المكوّن الخاصية <code>onClick</code> كي يقع حدث التنقل بالطريقة الصحيحة.


== الحالة التي يكون فيها ابن المكوّن <code>link</code> مكوّن دالة ==
== الحالة التي يكون فيها ابن المكون <code>link</code> مكون دالة ==
لا بد في هذه الحالة من تغليف المكوّن ضمن [[React/react-api.html#reactforwardref|<code>React.forwardRef</code>]] إضافةً إلى استخدام الخاصية <code>passHref</code>:<syntaxhighlight lang="javascript">
لا بد في هذه الحالة من تغليف المكوّن ضمن <code>[[React/react api#reactforwardref|React.forwardRef]]</code> إضافةً إلى استخدام الخاصية <code>passHref</code> والخاصية <code>legacyBehavior</code>:<syntaxhighlight lang="javascript">
import Link from 'next/link'
import Link from 'next/link'


سطر 96: سطر 120:
function Home() {
function Home() {
   return (
   return (
     <Link href="/about" passHref>
     <Link href="/about" passHref legacyBehavior>
       <MyButton />
       <MyButton />
     </Link>
     </Link>
سطر 119: سطر 143:
           }}
           }}
         >
         >
           <a>About us</a>
           About us
         </Link>
         </Link>
       </li>
       </li>
سطر 129: سطر 153:
           }}
           }}
         >
         >
           <a>Blog Post</a>
           Blog Post
         </Link>
         </Link>
       </li>
       </li>
سطر 137: سطر 161:


export default Home
export default Home
</syntaxhighlight>يحتوي المثال السابق روابط إلى:
</syntaxhighlight>يحتوي المثال السابق روابط إلى:


* <code>/about?name=test</code>: وجهة محددة مسبقًا.
* <code>about?name=test/</code>: وجهة محددة مسبقًا.
* <code>/blog/my-post</code>: وجهة ديناميكية.
* <code>blog/my-post/</code>: وجهة ديناميكية.


بإمكانك استعمال أية خاصية كما عُرّفت في [[Node.js/url|توثيق Node.js لوحدة URL]].
بإمكانك استعمال أية خاصية كما عُرّفت في [[Node.js/url|توثيق Node.js لوحدة URL]].


== استبدال العنوان في سجل العناوين بدلًا من دفعه ==
== استبدال العنوان في سجل العناوين بدلًا من دفعه ==
يدفع <code>push</code> المكوّن <code>Link</code> افتراضيًا عنوان URL الجديد في مكدس سجل العناوين <code>history</code>. لكن بإمكانك استخدام الخاصية <code>replace</code> لمنع إضافة مُدخل جديد إلى السجل كالتالي:<syntaxhighlight lang="javascript">
يدفع <code>push</code> المكوّن <code>Link</code> افتراضيًا عنوان URL الجديد في مكدس سجل العناوين <code>history</code>. لكن بإمكانك استخدام الخاصية <code>replace</code> لمنع إضافة مُدخل جديد إلى السجل كالتالي:<syntaxhighlight lang="javascript">
<Link href="/about" replace>
<Link href="/about" replace>
   <a>About us</a>
   About us
</Link>
</Link>
</syntaxhighlight>
</syntaxhighlight>
سطر 154: سطر 179:
يقتضي السلوك الافتراضي للمكوّن <code>link</code> بالانتقال إلى أعلى الصفحة. لكن عند وجود إشارة العنوان الفرعي (#) سينتقل بالصفحة إلى هذا العنوان المحدد كما يفعل أي رابط نمطي <code><a></code>. لهذا إن أردت إلغاء السلوك الافتراضي بالانتقال إلى أعلى الصفحة، استخدم الصيغة التالية:<syntaxhighlight lang="javascript">
يقتضي السلوك الافتراضي للمكوّن <code>link</code> بالانتقال إلى أعلى الصفحة. لكن عند وجود إشارة العنوان الفرعي (#) سينتقل بالصفحة إلى هذا العنوان المحدد كما يفعل أي رابط نمطي <code><a></code>. لهذا إن أردت إلغاء السلوك الافتراضي بالانتقال إلى أعلى الصفحة، استخدم الصيغة التالية:<syntaxhighlight lang="javascript">
<Link href="/#hashid" scroll={false}>
<Link href="/#hashid" scroll={false}>
   <a>Disables scrolling to the top</a>
   Disables scrolling to the top
</Link>
</Link>
</syntaxhighlight>
</syntaxhighlight>
== البرمجيات الوسيطة Middleware ==
يشيع استعمال [[Next.js/middleware|البرمجيات الوسيطة Middleware]] في عمليات الاستيثاق authentication أو غيرها من الحالات التي تتطلب إعادة توجيه المستخدم إلى صفحة أخرى غير التي يريد الانتقال إليها، فإن أردت أن يجلب المكون <code><Link></code> المكون المشار إليه في المسار مسبقًا بشكل صحيح مع حالة إعادة التوجيه التي قد تجريها إحدى البرمجيات الوسيطة، تحتاج إلى إخبار Next.js صراحةً أي عنوان URL يُعرض وأي عنوان يُجلب مسبقًا، وهذا ضروري لتجنب إجراء عمليات جلب غير ضرورية للبرمجيات الوسيطة لمعرفة الوجهة الصحيحة المراد جلبها مسبقًا.
إليك مثال، إن أردت تخديم وجهة ‎<code>/dashboard</code> تتطلب من المستخدم إجراء الاستيثاق قبل رؤيتها، فعليك إضافة شيفرة مشابهة للشيفرة التالية في ملف البرمجيات الوسيطة middleware.js لإعادة توجيه المستخدم للصفحة الصحيحة:<syntaxhighlight lang="javascript">
// middleware.js
export function middleware(req) {
  const nextUrl = req.nextUrl
  if (nextUrl.pathname === '/dashboard') {
    if (req.cookies.authToken) {
      return NextResponse.rewrite('/auth/dashboard')
    } else {
      return NextResponse.rewrite('/public/dashboard')
    }
  }
}
</syntaxhighlight>في هذه الحالة يجب أن تستخدم الرابط <Link> بالشكل التالي (داخل مجلد الصفحات /pages):<syntaxhighlight lang="javascript">
// pages/index.js
import Link from 'next/link'
import useIsAuthed from './hooks/useIsAuthed'
export default function Page() {
  const isAuthed = useIsAuthed()
  const path = isAuthed ? '/auth/dashboard' : '/dashboard'
  return (
    <Link as="/dashboard" href={path}>
      Dashboard
    </Link>
  )
}
</syntaxhighlight>'''ملاحظة''': إن تستخدم [[Next.js/Routing#.D8.A7.D9.84.D9.88.D8.AC.D9.87.D8.A7.D8.AA .D8.A7.D9.84.D8.AF.D9.8A.D9.86.D8.A7.D9.85.D9.8A.D9.83.D9.8A.D8.A9 Dynamic Routes|الوجهات الديناميكية]]،  فستحتاج إلى إلى ضبط الخاصية <code>as</code> والخاصية <code>href</code>، مثلًا إن كان لديك الوجهة الديناميكية ‎<code>/dashboard/[user]</code> التي تريد عرضها بشكل مختلف عبر البرمجيات الوسيطة، فيجب أن يكون <code><Link></code> بالشكل التالي:<syntaxhighlight lang="javascript">
<Link href={{ pathname: '/dashboard/authed/[user]', query: { user: username } }} as="/dashboard/[user]">Profile</Link>
</syntaxhighlight>
== أمثلة ==
* [https://github.com/vercel/next.js/tree/canary/examples/hello-world Hello World]
* [https://github.com/vercel/next.js/tree/canary/examples/active-class-name Active className on Link]


== المصادر ==
== المصادر ==


* الصفحة [https://nextjs.org/docs/api-reference/next/link Next/Link] من توثيق Next.js الرسمي.
* الصفحة [https://nextjs.org/docs/api-reference/next/link Next/Link] من توثيق Next.js الرسمي.
[[تصنيف:Next.js|{{SUBPAGENAME}}]]
[[تصنيف:Next.js API|{{SUBPAGENAME}}]]

المراجعة الحالية بتاريخ 19:43، 4 يناير 2023

ننصحك قبل قراءة المقال بالاطلاع على التوجيه في Next.js أولًا.

بإمكانك تفعيل التنقل بين الصفحات أو الوجهات في جانب العميل عبر المكوّن Link المستورد عبر next/link.

لنفترض وجود الملفات التالية في المجلد pages:

  • pages/index.js
  • pages/about.js
  • pages/blog/[slug].js

يمكننا الحصول على رابط إلى كل صفحة من هذه الصفحات كالتالي:

import Link from 'next/link'

function Home() {
  return (
    <ul>
      <li>
        <Link href="/">Home</Link>
      </li>
      <li>
        <Link href="/about">About Us</Link>
      </li>
      <li>
        <Link href="/blog/hello-world">Blog Post</Link>
      </li>
    </ul>
  )
}

export default Home

يقبل المكوّن Link الخاصيات التالية:

  • href: المسار أو عنوان URL الذي سننتقل إليه. وهذه الخاصية هي الوحيدة التي نحتاجها، كما يمكن أن تكون كائنًا (كائن URL).
  • as: منسّق اختياري للمسار الذي سيُعرض في شريط عناوين المتصفح. استُخدم هذا المعامل سابقًا للتوجه الديناميكي ما قبل الإصدار 9.5.3. ملاحظة: إن اختلف المسار هذا المعطى عن المسار المعطى في href فإن سلوك href/as القديم المستخدم في ذلك الإصدار هو الذي سيُستخدم، فارجع إلى التوثيق القديم.
  • legacyBehavior: يغير السلوك ويعود للسلوك القديم الذي يتطلب وجود عنصر <a> ابن، ويأخذ القيمة الافتراضية false.
  • passHref: يجبر المكوّن Link على إرسال الخاصية href إلى أبناءه، ويأخذ القيمة الافتراضية false.
  • prefetch: يحضر الصفحة مسبقًا وراء الستار، ويأخذ القيمة الافتراضية true. كما سيُعاد تحميل أي مكوّن </ Link> ظاهر في نافذة العرض (في البداية أو عند التمرير). يمكن تعطيل هذه الخاصية بتمرير القيمة prefetch={false}. وعندما تأخذ الخاصية prefetch القيمة false، ستستمر عملية الإحضار المسبق عند مرور مؤشر الفأرة فوق العنصر hovering. ستعيد الصفحات التي تستخدم التوليد الساكن توليد ملفات JSON مع البيانات لتسريع عملية الانتقال بين الصفحات. تُفعّل الخاصية prefetch في مرحلة الإنتاج فقط.
  • replace: يستبدل حالة سجل العناوين history بدلًا من إضافة عنوان url جديد إلى المكدّس، ويأخذ القيمة الافتراضية false.
  • scroll: يتحكم بالتمرير إلى أعلى الصفحة بعد الانتقال، وقيمته الافتراضية true.
  • shallow: يُحدّث مسار الصفحة الحالية دون تنفيذ الدوال getStaticProps أو getServerSideProps أو getInitialProps، وقيمته الافتراضية false.
  • locale: يُستخدم الإعداد المحلي المُفعَّل تلقائيًا. كما يمكنك استخدامها لتغيير هذا الإعداد. عندما تأخذ الخاصية القيمة false يجب أن تحدد الخاصية href الإعداد المحلي بما أن السلوك الافتراضي قد تعطل آنذاك.

حالة وجود أجزاء ديناميكية في الوجهة

لا ينبغي عليك تنفيذ أي عملية محددة عندما ترتبط إلى الوجهات الديناميكية بما في ذلك التقاط جميع الوجهات، وذلك اعتبارًا من النسخة 9.5.3. لكن قد يكون مفيدًا في بعض الأحيان استخدام الاستدلال interpolation أو كائن URL لتوليد الرابط.

ستطابق الوجهة الديناميكية pages/blog/[slug].js مثلًا الرابط التالي:

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

حالة وجود مكون <a> ابن مخصص للمكون link

إليك المثال التالي الذي يمثل هذه الحالة:

import Link from 'next/link'

function Legacy() {
  return (
    <Link href="/about" legacyBehavior>
      <a>About Us</a>
    </Link>
  )
}

export default Legacy

حالة وجود مكون ابن مخصص للمكون link مغلف بالعنصر <a>

لا بد في هذه الحالة من إضافة الخاصية passHref إلى المكوّن link، وهذا ضروري إن كنت تستخدم مكتبات مثل styled-components. لن يمتلك العنصر <a> دون أن تفعل ذلك السمة href، الأمر الذي يسيء إلى سهولة وصول موقعك وقد يؤثر على نتيجة البحث SEO. وفي حال استخدمت المدقق ESLint، تأكد من استخدام القاعدة next/link-passhref للتأكد من الاستخدام الصحيح للخاصية passHref:

import Link from 'next/link'
import styled from 'styled-components'

// <a> يُنشئ ذلك مكوّن مخصص يغلف العنصر 
const RedLink = styled.a`
  color: red;
`
function NavLink({ href, name }) {
  //Link إلى الرابط href لا بد من إضافة 
  return (
    <Link href={href} passHref legacyBehavior>
      <RedLink>{name}</RedLink>
    </Link>
  )
}

export default NavLink
  • لا بد أيضًا من استخدام الخاصية passHref إن كنت ستعمل مع الميزة jsx jsx@ العائدة لمكتبة التنسيق emotion حتى لو استخدمت <a> مباشرة.
  • يجب أن يدعم المكوّن الخاصية onClick كي يقع حدث التنقل بالطريقة الصحيحة.

الحالة التي يكون فيها ابن المكون link مكون دالة

لا بد في هذه الحالة من تغليف المكوّن ضمن React.forwardRef إضافةً إلى استخدام الخاصية passHref والخاصية legacyBehavior:

import Link from 'next/link'

//DOM عبر شجرة `onClick`و `href`و `ref` لا بد من تمرير
// ليجري التعامل معها بالشكل الصحيح
const MyButton = React.forwardRef(({ onClick, href }, ref) => {
  return (
    <a href={href} onClick={onClick} ref={ref}>
      Click Me
    </a>
  )
})

function Home() {
  return (
    <Link href="/about" passHref legacyBehavior>
      <MyButton />
    </Link>
  )
}

export default Home

حالة استقبال كائن URL

يستقبل المكوّن Link كائن URL وينسقه تلقائيًا لإنشاء عنوان URL نصي. إليك الطريقة:

import Link from 'next/link'

function Home() {
  return (
    <ul>
      <li>
        <Link
          href={{
            pathname: '/about',
            query: { name: 'test' },
          }}
        >
          About us
        </Link>
      </li>
      <li>
        <Link
          href={{
            pathname: '/blog/[slug]',
            query: { slug: 'my-post' },
          }}
        >
          Blog Post
        </Link>
      </li>
    </ul>
  )
}

export default Home

يحتوي المثال السابق روابط إلى:

  • about?name=test/: وجهة محددة مسبقًا.
  • blog/my-post/: وجهة ديناميكية.

بإمكانك استعمال أية خاصية كما عُرّفت في توثيق Node.js لوحدة URL.

استبدال العنوان في سجل العناوين بدلًا من دفعه

يدفع push المكوّن Link افتراضيًا عنوان URL الجديد في مكدس سجل العناوين history. لكن بإمكانك استخدام الخاصية replace لمنع إضافة مُدخل جديد إلى السجل كالتالي:

<Link href="/about" replace>
  About us
</Link>

إلغاء التمرير إلى أعلى الصفحة

يقتضي السلوك الافتراضي للمكوّن link بالانتقال إلى أعلى الصفحة. لكن عند وجود إشارة العنوان الفرعي (#) سينتقل بالصفحة إلى هذا العنوان المحدد كما يفعل أي رابط نمطي <a>. لهذا إن أردت إلغاء السلوك الافتراضي بالانتقال إلى أعلى الصفحة، استخدم الصيغة التالية:

<Link href="/#hashid" scroll={false}>
  Disables scrolling to the top
</Link>

البرمجيات الوسيطة Middleware

يشيع استعمال البرمجيات الوسيطة Middleware في عمليات الاستيثاق authentication أو غيرها من الحالات التي تتطلب إعادة توجيه المستخدم إلى صفحة أخرى غير التي يريد الانتقال إليها، فإن أردت أن يجلب المكون <Link> المكون المشار إليه في المسار مسبقًا بشكل صحيح مع حالة إعادة التوجيه التي قد تجريها إحدى البرمجيات الوسيطة، تحتاج إلى إخبار Next.js صراحةً أي عنوان URL يُعرض وأي عنوان يُجلب مسبقًا، وهذا ضروري لتجنب إجراء عمليات جلب غير ضرورية للبرمجيات الوسيطة لمعرفة الوجهة الصحيحة المراد جلبها مسبقًا.

إليك مثال، إن أردت تخديم وجهة ‎/dashboard تتطلب من المستخدم إجراء الاستيثاق قبل رؤيتها، فعليك إضافة شيفرة مشابهة للشيفرة التالية في ملف البرمجيات الوسيطة middleware.js لإعادة توجيه المستخدم للصفحة الصحيحة:

// middleware.js
export function middleware(req) {
  const nextUrl = req.nextUrl
  if (nextUrl.pathname === '/dashboard') {
    if (req.cookies.authToken) {
      return NextResponse.rewrite('/auth/dashboard')
    } else {
      return NextResponse.rewrite('/public/dashboard')
    }
  }
}

في هذه الحالة يجب أن تستخدم الرابط <Link> بالشكل التالي (داخل مجلد الصفحات /pages):

// pages/index.js
import Link from 'next/link'
import useIsAuthed from './hooks/useIsAuthed'

export default function Page() {
  const isAuthed = useIsAuthed()
  const path = isAuthed ? '/auth/dashboard' : '/dashboard'
  return (
    <Link as="/dashboard" href={path}>
      Dashboard
    </Link>
  )
}

ملاحظة: إن تستخدم الوجهات الديناميكية، فستحتاج إلى إلى ضبط الخاصية as والخاصية href، مثلًا إن كان لديك الوجهة الديناميكية ‎/dashboard/[user] التي تريد عرضها بشكل مختلف عبر البرمجيات الوسيطة، فيجب أن يكون <Link> بالشكل التالي:

<Link href={{ pathname: '/dashboard/authed/[user]', query: { user: username } }} as="/dashboard/[user]">Profile</Link>

أمثلة

المصادر

  • الصفحة Next/Link من توثيق Next.js الرسمي.