loading.js و error.js در Next.js؛ لودینگ و خطای تمیز با App Router
نویسنده: آرش لطیفی
آموزش عملی loading.js و error.js در Next.js App Router با Suspense و استریمینگ؛ اسکلت لودینگ، مدیریت خطا و دکمه تلاش مجدد.
TL;DR — با
loading.jsاسکلت لودینگ خودکار و باerror.js(کامپوننت کلاینتی + دکمهreset) خطای تمیز بده؛ برای جزئیات بیشترSuspenseرو دور بخشهای کند بپیچ.
ایده اصلی چیه؟
تو App Router کافیه کنار هر page.js یه فایل loading.js بذاری تا موقع لود شدن دیتا خودش نمایش داده بشه، و یه error.js بذاری تا اگه چیزی ترکید، بهجای صفحه سفید یه پیام درست با دکمه «تلاش مجدد» نشون بده. نه setTimeout دستی، نه isLoading پخشوپلا تو همه کامپوننتها.
نکته مهم: loading.js فقط وقتی کار میکنه که صفحهات واقعاً آسنک باشه (fetch یا دیتای داینامیک). اگه صفحه استاتیکه و فوری رندر میشه، لودینگ نشون داده نمیشه و طبیعیه.
اسکلت لودینگ با loading.js
یه اسکلت ساده که شکل صفحه واقعی رو تقلید میکنه؛ کاربر حس میکنه صفحه داره میاد، نه اینکه هنگ کرده:
اگه کل صفحه رو نمیخوای بلوکه کنی، Suspense رو فقط دور بخش کند بپیچ تا بقیه صفحه فوری بیاد (استریمینگ). این ترفند با بهینهسازی تصاویر ترکیبش عالی میشه چون عکسها معمولاً کندترین بخشان:
خطای تمیز با error.js
فایل خطا حتماً باید کامپوننت کلاینتی باشه ("use client") و دو تا prop میگیره: خود error و تابع reset برای تلاش مجدد:
یادت نره خطا رو لاگ کنی (Sentry یا هر سرویسی که داری). error.js فقط نزدیکترین سگمنت والد رو میگیره؛ یعنی هدر و فوتر سایت سر جاش میمونن و فقط باکس وسط پیام خطا نشون میده. اگه کل اپ ترکید (مثلاً روتلایوت)، اون با global-error.js هندل میشه.
مقایسه سریع راهها
| روش | کِی خوبه | کِی بده |
| --- | --- | --- |
| loading.js | لودینگ کل سگمنت، صفر کد اضافه | کل بخش رو بلوکه میکنه |
| Suspense دور بخش کند | استریمینگ واقعی، UX بهتر | یه کم کد بیشتر |
| error.js + reset | خطای محدود + تلاش مجدد | فقط خطای رندر/دیتای همون سگمنت |
| try/catch دستی | منطق خاص هر اکشن | تکرار کد تو همهجا |
قانون سرانگشتی: loading.js برای شروع، Suspense برای صفحههای مهم فروش، error.js همهجا.
چکلیست
- [x] هر روت دیتامحور یه
loading.jsبا اسکلت همشکل صفحه داره - [x]
error.jsکلاینتیه و دکمه تلاش مجدد (reset) داره - [x] خطاها لاگ میشن، نه فقط نمایش
- [ ] بخشهای کند صفحههای مهم با
Suspenseجدا شدن (مثل لیست محصولات) - [ ] رفتار خطا یه بار دستی تست شده (مثلاً قطع API)
- [ ] اگه احراز هویت داری، با راهنمای middleware چکش کن که ریدایرکت لاگین با باندری خطا قاطی نشه
سوالات پرتکرار
چرا loading.js من نشون داده نمیشه؟
چون صفحهات استاتیک رندر میشه. تا fetch داینامیک یا await واقعی نباشه، صفحه فوری آمادهست و لودینگی در کار نیست. با Suspense دور کامپوننت آسنک تست کن.
reset دقیقاً چی کار میکنه؟
سگمنت خطادار رو دوباره رندر میکنه بدون رفرش کل صفحه. اگه مشکل موقتی بوده (API یه لحظه خوابیده)، درست میشه؛ اگه دائمیه، دوباره همون خطا میاد.
error.js خطای کدوم لایه رو نمیگیره؟
خطاهای روتلایوت و خطاهای سرورِ بیرون از رندر (مثل میدلور) رو نه. برای اولی global-error.js بذار، دومی رو باید جدا هندل کنی.