الفرق بين المراجعتين لصفحة: «Next.js/layouts»
لا ملخص تعديل |
جميل-بيلوني (نقاش | مساهمات) ط مراجعة وتدقيق |
||
سطر 20: | سطر 20: | ||
=== تخطيط مشترك واحد لتطبيق مخصص === | === تخطيط مشترك واحد لتطبيق مخصص === | ||
إن كان لديك تخطيط واحد لكامل تطبيقك، بإمكانك إنشاء [[Next.js/custom app|تطبيق مخصص]] Custom App وتغليفه بتخطيط واحد. ونظرًا لاستخدام المكوّن <code></ Layout></code> من جديد عند تغيير الصفحة، ستُخزَّن حالته (مثل قيم الدخل).<syntaxhighlight lang="javascript"> | إن كان لديك تخطيط واحد لكامل تطبيقك، بإمكانك إنشاء [[Next.js/custom app|تطبيق مخصص]] Custom App وتغليفه بتخطيط واحد. ونظرًا لاستخدام المكوّن <code></ Layout></code> من جديد عند تغيير الصفحة، ستُخزَّن حالته (مثل قيم الدخل input).<syntaxhighlight lang="javascript"> | ||
// pages/_app.js | // pages/_app.js | ||
سطر 35: | سطر 35: | ||
=== تخطيطات على مستوى الصفحة === | === تخطيطات على مستوى الصفحة === | ||
بإمكانك إن احتجت إلى عدة تخطيطات، إضافة الخاصية <code>getLayout</code> إلى صفحتك التي تعيد مكوّن React لتخطيط الصفحة. يسمح ذلك بتعريف تخطيطٍ على مستوى الصفحة per-page، إذ يسمح إعادة الدالة بالحصول على تخطيطات معقدة متداخلة إن أردنا ذلك.<syntaxhighlight lang="javascript"> | بإمكانك إن احتجت إلى عدة تخطيطات، إضافة الخاصية <code>getLayout</code> إلى صفحتك التي تعيد مكوّن [[React/components and props|React]] لتخطيط الصفحة. يسمح ذلك بتعريف تخطيطٍ على مستوى الصفحة per-page، إذ يسمح إعادة الدالة بالحصول على تخطيطات معقدة متداخلة إن أردنا ذلك.<syntaxhighlight lang="javascript"> | ||
// pages/index.js | // pages/index.js | ||
سطر 54: | سطر 54: | ||
) | ) | ||
} | } | ||
</syntaxhighlight><syntaxhighlight lang="javascript"> | |||
// pages/_app.js | // pages/_app.js | ||
سطر 62: | سطر 63: | ||
return getLayout(<Component {...pageProps} />) | return getLayout(<Component {...pageProps} />) | ||
} | } | ||
</syntaxhighlight>عند التنقل بين الصفحات، لا بد أن تحافظ على حالة الصفحة (قيم الدخل، موقع شريط التمرير وغير ذلك) لضمان تجربة جيدة في التطبيقات وحيدة الصفحة Single-Page Application. يُمكِّن نمط التخطيط هذا من الحفاظ على الحالة، لأن شجرة مكوّن React سيبقى كما هو عند التنقل بين الصفحات. إذ تتيح شجرة المكوِّن لتطبيق React أن يَعرف أي العناصر قد تغيرت ليخزِّن الحالة. | </syntaxhighlight>عند التنقل بين الصفحات، لا بد أن تحافظ على حالة الصفحة (قيم الدخل، موقع شريط التمرير وغير ذلك) لضمان تجربة جيدة في التطبيقات وحيدة الصفحة Single-Page Application. يُمكِّن نمط التخطيط هذا من الحفاظ على الحالة، لأن شجرة مكوّن React سيبقى كما هو عند التنقل بين الصفحات. إذ تتيح شجرة المكوِّن لتطبيق React أن يَعرف أي العناصر قد تغيرت ليخزِّن الحالة. | ||
'''ملاحظة:''' تُدعى هذه العملية [[React/reconciliation|بالمطابقة]] reconciliation، وهي الطريقة التي تعرف فيها React أية عناصر قد تغيّرت | |||
=== مشاركة TypeScript === | === مشاركة TypeScript === | ||
لا بد أن تنشئ نوعًا جديدًا لصفحاتك يتضمن الدالة <code>getLayout</code> إن أردت استخدام [[TypeScript]]. ثم عليك أن تنشئ بعد ذلك نوعًا جديدًا لتطبيقك يلغي خاصيات المكوّن كي يستخدم النوع الذي أنشئ سابقًا.<syntaxhighlight lang="javascript"> | لا بد أن تنشئ نوعًا جديدًا لصفحاتك يتضمن الدالة <code>getLayout</code> إن أردت استخدام [[TypeScript]]. ثم عليك أن تنشئ بعد ذلك نوعًا جديدًا لتطبيقك يلغي خاصيات المكوّن كي يستخدم النوع الذي أنشئ سابقًا.<syntaxhighlight lang="javascript"> | ||
سطر 71: | سطر 73: | ||
import Layout from '../components/layout' | import Layout from '../components/layout' | ||
import NestedLayout from '../components/nested-layout' | import NestedLayout from '../components/nested-layout' | ||
import type { NextPageWithLayout } from './_app' | |||
const Page: NextPageWithLayout = () => { | |||
return | return <p>hello world</p> | ||
} | } | ||
سطر 85: | سطر 86: | ||
) | ) | ||
} | } | ||
export default Page | |||
</syntaxhighlight><syntaxhighlight lang="javascript"> | |||
// pages/_app.tsx | // pages/_app.tsx | ||
سطر 91: | سطر 95: | ||
import type { AppProps } from 'next/app' | import type { AppProps } from 'next/app' | ||
type NextPageWithLayout = NextPage & { | export type NextPageWithLayout = NextPage & { | ||
getLayout?: (page: ReactElement) => ReactNode | getLayout?: (page: ReactElement) => ReactNode | ||
} | } | ||
سطر 102: | سطر 106: | ||
//استخدم التخطيط المعرّف على مستوى الصفحة إن كان متاحًا | //استخدم التخطيط المعرّف على مستوى الصفحة إن كان متاحًا | ||
const getLayout = Component.getLayout ?? ((page) => page) | const getLayout = Component.getLayout ?? ((page) => page) | ||
return getLayout(<Component {...pageProps} />) | return getLayout(<Component {...pageProps} />) | ||
} | } | ||
سطر 107: | سطر 112: | ||
=== إحضار البيانات === | === إحضار البيانات === | ||
يمكنك [[Next.js/data fetching|إحضار البيانات]] من جانب العميل إلى التخطيط باستخدام الخطاف <code>useEffect</code> أو المكتبة SWR. لا يمكنك استخدام الدالتين <code>getStaticProps</code> أو <code>getServerSideProps</code> حاليًا لأن هذا الملف ليس [[Next.js/pages|صفحة]].<syntaxhighlight lang="javascript"> | يمكنك [[Next.js/data fetching|إحضار البيانات]] من جانب العميل إلى التخطيط باستخدام الخطاف <code>[[React/hooks effect|useEffect]]</code> أو المكتبة [https://swr.vercel.app/ SWR]. لا يمكنك استخدام الدالتين <code>getStaticProps</code> أو <code>getServerSideProps</code> حاليًا لأن هذا الملف ليس [[Next.js/pages|صفحة]].<syntaxhighlight lang="javascript"> | ||
// components/layout.js | // components/layout.js | ||
سطر 129: | سطر 134: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== انظر أيضًا == | |||
* [[Next.js/pages|الصفحات في Next.js]] | |||
* [[Next.js/custom app|التطبيقات المخصصة باستخدام المكوّن App في Next.js]] | |||
== المصادر == | == المصادر == | ||
* صفحة [https://nextjs.org/docs/basic-features/layouts Layouts] في توثيق Next.js الرسمي. | * صفحة [https://nextjs.org/docs/basic-features/layouts Layouts] في توثيق Next.js الرسمي. |
مراجعة 15:53، 2 أغسطس 2022
يتيح لك نموذج React تفكيك الصفحة إلى سلسلة من المكوّنات التي يمكن الاستفادة من عدد منها في صفحات أخرى. فقد يكون للصفحات مثلًا شريط التنقل نفسه والتذييل نفسه.
// components/layout.js
import Navbar from './navbar'
import Footer from './footer'
export default function Layout({ children }) {
return (
<>
<Navbar />
<main>{children}</main>
<Footer />
</>
)
}
أمثلة عن تخطيط الصفحات في Next.js
تخطيط مشترك واحد لتطبيق مخصص
إن كان لديك تخطيط واحد لكامل تطبيقك، بإمكانك إنشاء تطبيق مخصص Custom App وتغليفه بتخطيط واحد. ونظرًا لاستخدام المكوّن </ Layout>
من جديد عند تغيير الصفحة، ستُخزَّن حالته (مثل قيم الدخل input).
// pages/_app.js
import Layout from '../components/layout'
export default function MyApp({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
)
}
تخطيطات على مستوى الصفحة
بإمكانك إن احتجت إلى عدة تخطيطات، إضافة الخاصية getLayout
إلى صفحتك التي تعيد مكوّن React لتخطيط الصفحة. يسمح ذلك بتعريف تخطيطٍ على مستوى الصفحة per-page، إذ يسمح إعادة الدالة بالحصول على تخطيطات معقدة متداخلة إن أردنا ذلك.
// pages/index.js
import Layout from '../components/layout'
import NestedLayout from '../components/nested-layout'
export default function Page() {
return {
/** المحتوى الخاص بك */
}
}
Page.getLayout = function getLayout(page) {
return (
<Layout>
<NestedLayout>{page}</NestedLayout>
</Layout>
)
}
// pages/_app.js
export default function MyApp({ Component, pageProps }) {
//استخدم التخطيط المعرّف على مستوى الصفحة إن كان متاحًا
const getLayout = Component.getLayout || ((page) => page)
return getLayout(<Component {...pageProps} />)
}
عند التنقل بين الصفحات، لا بد أن تحافظ على حالة الصفحة (قيم الدخل، موقع شريط التمرير وغير ذلك) لضمان تجربة جيدة في التطبيقات وحيدة الصفحة Single-Page Application. يُمكِّن نمط التخطيط هذا من الحفاظ على الحالة، لأن شجرة مكوّن React سيبقى كما هو عند التنقل بين الصفحات. إذ تتيح شجرة المكوِّن لتطبيق React أن يَعرف أي العناصر قد تغيرت ليخزِّن الحالة.
ملاحظة: تُدعى هذه العملية بالمطابقة reconciliation، وهي الطريقة التي تعرف فيها React أية عناصر قد تغيّرت
مشاركة TypeScript
لا بد أن تنشئ نوعًا جديدًا لصفحاتك يتضمن الدالة getLayout
إن أردت استخدام TypeScript. ثم عليك أن تنشئ بعد ذلك نوعًا جديدًا لتطبيقك يلغي خاصيات المكوّن كي يستخدم النوع الذي أنشئ سابقًا.
// pages/index.tsx
import type { ReactElement } from 'react'
import Layout from '../components/layout'
import NestedLayout from '../components/nested-layout'
import type { NextPageWithLayout } from './_app'
const Page: NextPageWithLayout = () => {
return <p>hello world</p>
}
Page.getLayout = function getLayout(page: ReactElement) {
return (
<Layout>
<NestedLayout>{page}</NestedLayout>
</Layout>
)
}
export default Page
// pages/_app.tsx
import type { ReactElement, ReactNode } from 'react'
import type { NextPage } from 'next'
import type { AppProps } from 'next/app'
export type NextPageWithLayout = NextPage & {
getLayout?: (page: ReactElement) => ReactNode
}
type AppPropsWithLayout = AppProps & {
Component: NextPageWithLayout
}
export default function MyApp({ Component, pageProps }: AppPropsWithLayout) {
//استخدم التخطيط المعرّف على مستوى الصفحة إن كان متاحًا
const getLayout = Component.getLayout ?? ((page) => page)
return getLayout(<Component {...pageProps} />)
}
إحضار البيانات
يمكنك إحضار البيانات من جانب العميل إلى التخطيط باستخدام الخطاف useEffect
أو المكتبة SWR. لا يمكنك استخدام الدالتين getStaticProps
أو getServerSideProps
حاليًا لأن هذا الملف ليس صفحة.
// components/layout.js
import useSWR from 'swr'
import Navbar from './navbar'
import Footer from './footer'
export default function Layout({ children }) {
const { data, error } = useSWR('/api/navigation', fetcher)
if (error) return <div>Failed to load</div>
if (!data) return <div>Loading...</div>
return (
<>
<Navbar links={data.links} />
<main>{children}</main>
<Footer />
</>
)
}
انظر أيضًا
المصادر
- صفحة Layouts في توثيق Next.js الرسمي.