جلب البيانات، التخزين المؤقت، وإعادة التحقق
يعد جلب البيانات جزءًا أساسيًا من أي تطبيق. توضح هذه الصفحة كيفية جلب البيانات، تخزينها مؤقتًا، وإعادة التحقق منها في React وNext.js.
هناك أربع طرق لجلب البيانات:
- على الخادم باستخدام
fetch
- على الخادم باستخدام مكتبات الطرف الثالث
- على العميل عبر معالج المسار (Route Handler)
- على العميل باستخدام مكتبات الطرف الثالث.
جلب البيانات على الخادم باستخدام fetch
يمتد Next.js واجهة برمجة تطبيقات fetch
الأصلية للسماح لك بتكوين سلوك التخزين المؤقت وإعادة التحقق لكل طلب جلب بيانات على الخادم. يمتد React fetch
لتلقائيًا تذكر طلبات الجلب أثناء عرض شجرة مكونات React.
يمكنك استخدام fetch
مع async
/await
في مكونات الخادم، معالجات المسار (Route Handlers)، وإجراءات الخادم (Server Actions).
مثال:
async function getData() {
const res = await fetch('https://api.example.com/...')
// القيمة المرجعة *ليست* متسلسلة
// يمكنك إرجاع Date, Map, Set, إلخ.
if (!res.ok) {
// سيؤدي هذا إلى تفعيل أقرب حد خطأ `error.js`
throw new Error('Failed to fetch data')
}
return res.json()
}
export default async function Page() {
const data = await getData()
return <main></main>
}
async function getData() {
const res = await fetch('https://api.example.com/...')
// القيمة المرجعة *ليست* متسلسلة
// يمكنك إرجاع Date, Map, Set, إلخ.
if (!res.ok) {
// سيؤدي هذا إلى تفعيل أقرب حد خطأ `error.js`
throw new Error('Failed to fetch data')
}
return res.json()
}
export default async function Page() {
const data = await getData()
return <main></main>
}
معلومة مفيدة:
- يوفر Next.js دوال مساعدة قد تحتاجها عند جلب البيانات في مكونات الخادم مثل
cookies
وheaders
. سيؤدي هذا إلى عرض المسار بشكل ديناميكي حيث يعتمد على معلومات وقت الطلب.- في معالجات المسار (Route Handlers)، لا يتم تذكر طلبات
fetch
لأن معالجات المسار ليست جزءًا من شجرة مكونات React.- في إجراءات الخادم (Server Actions)، لا يتم تخزين طلبات
fetch
مؤقتًا (الإعداد الافتراضيcache: no-store
).- لاستخدام
async
/await
في مكون خادم مع TypeScript، ستحتاج إلى استخدام TypeScript5.1.3
أو أعلى و@types/react
18.2.8
أو أعلى.
تخزين البيانات مؤقتًا
يخزن التخزين المؤقت البيانات حتى لا تحتاج إلى إعادة جلبها من مصدر البيانات في كل طلب.
افتراضيًا، يقوم Next.js تلقائيًا بتخزين القيم المرجعة من fetch
في ذاكرة التخزين المؤقت للبيانات (Data Cache) على الخادم. هذا يعني أنه يمكن جلب البيانات في وقت البناء أو وقت الطلب، تخزينها مؤقتًا، وإعادة استخدامها في كل طلب بيانات.
// 'force-cache' هو الإعداد الافتراضي، ويمكن حذفه
fetch('https://...', { cache: 'force-cache' })
ومع ذلك، هناك استثناءات، لا يتم تخزين طلبات fetch
مؤقتًا عندما:
- تستخدم داخل إجراء خادم (Server Action).
- تستخدم داخل معالج مسار (Route Handler) يستخدم طريقة
POST
.
ما هي ذاكرة التخزين المؤقت للبيانات (Data Cache)؟
ذاكرة التخزين المؤقت للبيانات هي ذاكرة تخزين مؤقت HTTP دائمة. اعتمادًا على منصتك، يمكن أن تتوسع الذاكرة المؤقتة تلقائيًا وتكون مشتركة عبر مناطق متعددة.
تعلم المزيد عن ذاكرة التخزين المؤقت للبيانات.
إعادة التحقق من البيانات
إعادة التحقق هي عملية مسح ذاكرة التخزين المؤقت للبيانات وإعادة جلب أحدث البيانات. هذا مفيد عندما تتغير بياناتك وتريد التأكد من عرض أحدث المعلومات.
يمكن إعادة التحقق من البيانات المخزنة مؤقتًا بطريقتين:
- إعادة التحقق المبنية على الوقت: إعادة التحقق من البيانات تلقائيًا بعد مرور فترة زمنية معينة. هذا مفيد للبيانات التي تتغير نادرًا ولا تكون الحداثة فيها حرجة.
- إعادة التحقق عند الطلب: إعادة التحقق من البيانات يدويًا بناءً على حدث (مثل تقديم نموذج). يمكن أن تستخدم إعادة التحقق عند الطلب نهجًا قائمًا على العلامات أو المسار لإعادة التحقق من مجموعات البيانات دفعة واحدة. هذا مفيد عندما تريد التأكد من عرض أحدث البيانات في أسرع وقت ممكن (مثل عند تحديث المحتوى من نظام إدارة المحتوى الخاص بك).
إعادة التحقق المبنية على الوقت
لإعادة التحقق من البيانات على فترات زمنية، يمكنك استخدام خيار next.revalidate
في fetch
لتعيين عمر ذاكرة التخزين المؤقت للمورد (بالثواني).
fetch('https://...', { next: { revalidate: 3600 } })
بدلاً من ذلك، لإعادة التحقق من جميع طلبات fetch
في جزء المسار، يمكنك استخدام خيارات تكوين الجزء (Segment Config Options).
export const revalidate = 3600 // إعادة التحقق على الأكثر كل ساعة
إذا كان لديك عدة طلبات جلب في مسار معروض بشكل ثابت، ولكل منها تردد إعادة تحقق مختلف. سيتم استخدام أقل وقت لجميع الطلبات. بالنسبة للمسارات المعروضة بشكل ديناميكي، سيتم إعادة التحقق من كل طلب fetch
بشكل مستقل.
تعلم المزيد عن إعادة التحقق المبنية على الوقت.
إعادة التحقق عند الطلب
يمكن إعادة التحقق من البيانات عند الطلب عن طريق المسار (revalidatePath
) أو عن طريق علامة التخزين المؤقت (revalidateTag
) داخل إجراء خادم (Server Action) أو معالج مسار (Route Handler).
يحتوي Next.js على نظام وضع علامات على الذاكرة المؤقتة لإبطال طلبات fetch
عبر المسارات.
- عند استخدام
fetch
، لديك خيار وضع علامة على إدخالات الذاكرة المؤقتة بواحدة أو أكثر من العلامات. - ثم يمكنك استدعاء
revalidateTag
لإعادة التحقق من جميع الإدخالات المرتبطة بهذه العلامة.
على سبيل المثال، يضيف طلب fetch
التالي علامة التخزين المؤقت collection
:
export default async function Page() {
const res = await fetch('https://...', { next: { tags: ['collection'] } })
const data = await res.json()
// ...
}
export default async function Page() {
const res = await fetch('https://...', { next: { tags: ['collection'] } })
const data = await res.json()
// ...
}
يمكنك بعد ذلك إعادة التحقق من استدعاء fetch
الموسوم بـ collection
عن طريق استدعاء revalidateTag
في إجراء خادم:
'use server'
import { revalidateTag } from 'next/cache'
export default async function action() {
revalidateTag('collection')
}
'use server'
import { revalidateTag } from 'next/cache'
export default async function action() {
revalidateTag('collection')
}
تعلم المزيد عن إعادة التحقق عند الطلب.
معالجة الأخطاء وإعادة التحقق
إذا حدث خطأ أثناء محاولة إعادة التحقق من البيانات، سيتم الاستمرار في تقديم آخر بيانات تم إنشاؤها بنجاح من الذاكرة المؤقتة. في الطلب التالي، سيقوم Next.js بإعادة محاولة إعادة التحقق من البيانات.
عدم استخدام تخزين البيانات مؤقتًا
لا يتم تخزين طلبات fetch
مؤقتًا إذا:
- تمت إضافة
cache: 'no-store'
إلى طلباتfetch
. - تمت إضافة خيار
revalidate: 0
إلى طلباتfetch
الفردية. - كان طلب
fetch
داخل معالج مسار (Route Handler) يستخدم طريقةPOST
. - جاء طلب
fetch
بعد استخدامheaders
أوcookies
. - تم استخدام خيار جزء المسار
const dynamic = 'force-dynamic'
. - تم تكوين خيار جزء المسار
fetchCache
لتخطي التخزين المؤقت افتراضيًا. - استخدم طلب
fetch
رؤوسAuthorization
أوCookie
وهناك طلب غير مخزن مؤقتًا فوقه في شجرة المكونات.
طلبات fetch
الفردية
لعدم تخزين طلبات fetch
الفردية مؤقتًا، يمكنك تعيين خيار cache
في fetch
إلى 'no-store'
. سيؤدي هذا إلى جلب البيانات بشكل ديناميكي، في كل طلب.
fetch('https://...', { cache: 'no-store' })
عرض جميع خيارات cache
المتاحة في مرجع واجهة برمجة تطبيقات fetch
.
طلبات fetch
المتعددة
إذا كان لديك عدة طلبات fetch
في جزء مسار (مثل تخطيط أو صفحة)، يمكنك تكوين سلوك التخزين المؤقت لجميع طلبات البيانات في الجزء باستخدام خيارات تكوين الجزء (Segment Config Options).
ومع ذلك، نوصي بتكوين سلوك التخزين المؤقت لكل طلب fetch
بشكل فردي. هذا يمنحك تحكمًا أدق في سلوك التخزين المؤقت.
جلب البيانات على الخادم باستخدام مكتبات الطرف الثالث
في الحالات التي تستخدم فيها مكتبة طرف ثالث لا تدعم أو تعرض fetch
(مثل قاعدة بيانات، نظام إدارة محتوى، أو عميل ORM)، يمكنك تكوين سلوك التخزين المؤقت وإعادة التحقق من تلك الطلبات باستخدام خيار تكوين جزء المسار (Route Segment Config Option) ودالة cache
في React.
سيعتمد ما إذا كانت البيانات مخزنة مؤقتًا أم لا على ما إذا كان جزء المسار معروضًا بشكل ثابت أو ديناميكي. إذا كان الجزء ثابتًا (افتراضيًا)، سيتم تخزين مخرجات الطلب مؤقتًا وإعادة التحقق منها كجزء من جزء المسار. إذا كان الجزء ديناميكيًا، لن يتم تخزين مخرجات الطلب مؤقتًا وسيتم إعادة جلبها في كل طلب عند عرض الجزء.
يمكنك أيضًا استخدام واجهة برمجة التطبيقات التجريبية unstable_cache
.
مثال
في المثال أدناه:
- يتم استخدام دالة React
cache
لتذكر طلبات البيانات. - تم تعيين خيار
revalidate
إلى3600
في أجزاء التخطيط والصفحة، مما يعني أنه سيتم تخزين البيانات مؤقتًا وإعادة التحقق منها على الأكثر كل ساعة.
import { cache } from 'react'
export const getItem = cache(async (id: string) => {
const item = await db.item.findUnique({ id })
return item
})
import { cache } from 'react'
export const getItem = cache(async (id) => {
const item = await db.item.findUnique({ id })
return item
})
على الرغم من استدعاء دالة getItem
مرتين، سيتم إجراء استعلام واحد فقط إلى قاعدة البيانات.
import { getItem } from '@/utils/get-item'
export const revalidate = 3600 // إعادة التحقق من البيانات على الأكثر كل ساعة
export default async function Layout({
params: { id },
}: {
params: { id: string }
}) {
const item = await getItem(id)
// ...
}
import { getItem } from '@/utils/get-item'
export const revalidate = 3600 // إعادة التحقق من البيانات على الأكثر كل ساعة
export default async function Layout({ params: { id } }) {
const item = await getItem(id)
// ...
}
import { getItem } from '@/utils/get-item'
export const revalidate = 3600 // إعادة التحقق من البيانات على الأكثر كل ساعة
export default async function Page({
params: { id },
}: {
params: { id: string }
}) {
const item = await getItem(id)
// ...
}
import { getItem } from '@/utils/get-item'
export const revalidate = 3600 // إعادة التحقق من البيانات على الأكثر كل ساعة
export default async function Page({ params: { id } }) {
const item = await getItem(id)
// ...
}
جلب البيانات على العميل باستخدام معالجات المسار (Route Handlers)
إذا كنت بحاجة إلى جلب البيانات في مكون عميل، يمكنك استدعاء معالج مسار (Route Handler) من العميل. تعمل معالجات المسار على الخادم وتعيد البيانات إلى العميل. هذا مفيد عندما لا تريد الكشف عن معلومات حساسة للعميل، مثل رموز API.
راجع وثائق معالج المسار (Route Handler) للحصول على أمثلة.
مكونات الخادم ومعالجات المسار
نظرًا لأن مكونات الخادم تعرض على الخادم، لا تحتاج إلى استدعاء معالج مسار من مكون خادم لجلب البيانات. بدلاً من ذلك، يمكنك جلب البيانات مباشرة داخل مكون الخادم.
جلب البيانات على العميل باستخدام مكتبات الطرف الثالث
يمكنك أيضًا جلب البيانات على العميل باستخدام مكتبات طرف ثالث مثل SWR أو TanStack Query. توفر هذه المكتبات واجهات برمجة تطبيقات خاصة بها لتذكر الطلبات، التخزين المؤقت، إعادة التحقق، وتحوير البيانات.
واجهات برمجة التطبيقات المستقبلية:
use
هي دالة React تقبل وتتعامل مع وعد (promise) تم إرجاعه بواسطة دالة. لا يوصى حاليًا **بتغليفfetch
فيuse
في مكونات العميل وقد يؤدي إلى إعادة عرض متعددة. تعلم المزيد عنuse
في وثائق React.