تله params ناهمگام در Next.js 15: چرا ۵۰٪ پروژهها با یک await میشکنند
نویسنده: آرش لطیفی
در Next.js 15 آبجکتهای params و searchParams ناهمگام شدند. بدون await صفحه میشکند یا stale میماند. الگوی درست، اشتباه رایج و فیکس ۳۰ ثانیهای.
خلاصه: در Next.js 15
paramsوsearchParamsدیگر آبجکت ساده نیستند —Promiseهستند. اگرawaitنکنی، در بیلد میشکند یا در رانتایم مقدار کهنه میگیری. این تله در ۵۰٪ مهاجرتها دیده میشود و با یک الگوی ۳ خطی حل میشود.
چرا ناهمگام شد؟
تا Next.js 14 این کد کار میکرد:
// Next.js 14 — کار میکرد
export default function Page({ params }: { params: { slug: string } }) {
return <h1>{params.slug}</h1>;
}
در Next.js 15 همان کد در بیلد اخطار میدهد و در رانتایم params.slug برابر undefined میشود. دلیل: تیم Next.js برای Partial Prerendering و کش دقیقتر params را Promise کرد تا رندر استاتیک و داینامیک از هم جدا شوند — تصمیم درست برای پرفورمنس، ولی بریکینگ برای همه.
اگر پروژهات هنوز روی مهاجرت Tailwind v4 یا بهینهسازی تصویر گیر است، این تله را اول فیکس کن؛ بقیه بعداً.
اشتباه رایج vs درست
❌ اشتباه ۱: بدون await
// ❌ میشکند — params یک Promise است
export default function Page({ params }: { params: Promise<{ slug: string }> }) {
const slug = params.slug; // undefined
return <h1>{slug}</h1>;
}
✅ درست: await در سرور کامپوننت
// ✅ درست — سرور کامپوننت async
export default async function Page({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
return <h1>{slug}</h1>;
}
❌ اشتباه ۲: generateMetadata بدون await
❌ اشتباه ۳: searchParams در کلاینت
چکلیست مهاجرت ۳۰ ثانیهای
جدول کوتاهِ اینکه کجا await لازم است و کجا نیست:
| محل استفاده | نوع در Next.js 15 | await لازم؟ |
|---|---|---|
| page.tsx / layout.tsx (سرور) | Promise | بله |
| generateMetadata | Promise | بله |
| Route Handler (route.ts) | Promise | بله |
| useParams() در کلاینت | مقدار آماده | خیر |
| generateStaticParams | ورودی ندارد | خیر |
| params تایپشده با any | خطا پنهان است | تایپ را اصلاح کن |
الگوی نهایی برای هر فایل page.tsx / layout.tsx:
چکلیست عملی بعد از مهاجرت:
- [ ] کدمود رسمی
next-async-request-apiروی کل پروژه اجرا شده - [ ] هیچ تایپ
anyبرایparamsیاsearchParamsباقی نمانده - [ ]
generateMetadataوgenerateViewportهر دوawaitدارند - [ ] روتهای داینامیک روی دیپلوی واقعی یک بار تست شدهاند، نه فقط روی
dev - [ ] خطای «Cannot access Request information synchronously» دیده نشده
کی await لازم نیست؟
- کلاینت کامپوننت با
useParams(): هوکuseParams()ازnext/navigationمقدار آماده میدهد — نیازی بهawaitنیست. این تله فقط برایpropsسرور است. generateStaticParams: خودشparamsرا میسازد و برمیگرداند — ورودی ندارد.
FAQ
Q: آیا باید همه پروژه را async کنم؟
فقط فایلهایی که params/searchParams میگیرند. بقیه میتوانند sync بمانند. ولی هر Page/Layout که این props را دارد باید async شود.
Q: چرا TypeScript خطا نمیدهد؟
اگر params را any تایپ کرده باشی، خطا مخفی میماند. Promise<{ slug: string }> را دقیق تایپ کن تا در tsc بفهمی.
Q: این با اعتبارسنجی فرم Zod تداخل دارد؟
نه — Zod در Server Action جداست. فقط اگر params را در همان Action بخوانی، آنجا هم await لازم است.
جمعبندی
Next.js 15 یک await به هر params اضافه کرد تا کش و PPR درست کار کند. اگر بعد از آپدیت صفحه سفید یا مقدار undefined دیدی، اول همین فایل را چک کن. یک await، کل سایت را نجات میدهد.
منابع
- راهنمای ارتقا به نسخه ۱۵ در مستندات Next.js — توضیح رسمی تغییر
paramsوsearchParamsبهPromise - مستندات کدمودهای Next.js — کدمود
next-async-request-apiکه در متن مقاله استفاده شده - پیام خطای Cannot access Request information synchronously — مرجع خطای رایج بعد از مهاجرت
- پرسش و پاسخ Params should be awaited — تجربهی کاربر در Route Handler
- پرسش و پاسخ Promise-based Params در prop expression — خطای تایپ در جای اشتباه