🔵 App Router – Pages, Layouts और Navigation · Lesson 14
loading, error और not-found Pages
तीन special files
- 1loading.jsx — page data fetch कर रहा हो तब दिखता है
- 2error.jsx — page में error आए तो दिखता है
- 3not-found.jsx — गलत URLs या notFound() पर दिखता है
loading.jsx — तुरंत loading state
Page slow database का इंतज़ार करे तो user को खाली screen दिखती है। Page के बगल में loading.jsx रखें तो Next.js उसे तुरंत दिखाता है, फिर असली page से बदल देता है।
JSX – app/blog/page.jsx (slow)
// app/blog/page.jsx — simulate a slow database
async function getPosts() {
await new Promise((r) => setTimeout(r, 2000)) // 2 seconds
return [{ slug: 'hello', title: 'Hello Next.js' }]
}
export default async function Blog() {
const posts = await getPosts()
return posts.map((p) => <h2 key={p.slug}>{p.title}</h2>)
}JSX + CSS – app/blog/loading.jsx skeleton
// app/blog/loading.jsx
export default function Loading() {
return (
<div className="container" aria-busy="true">
{[1, 2, 3].map((i) => (
<div key={i} className="skeleton-card">
<div className="sk sk-title" />
<div className="sk sk-line" />
<div className="sk sk-line short" />
</div>
))}
</div>
)
}
/* globals.css */
.sk { background: linear-gradient(90deg,#eee 25%,#f5f5f5 50%,#eee 75%);
background-size: 200% 100%; animation: shine 1.2s infinite; border-radius: 8px; }
.sk-title { height: 22px; width: 60%; margin-bottom: 10px; }
.sk-line { height: 12px; margin-bottom: 8px; }
.sk-line.short { width: 40%; }
@keyframes shine { to { background-position: -200% 0; } }Page के हिस्से के लिए Suspense
JSX – app/page.jsx
// app/page.jsx — hero appears instantly, reviews stream in later
import { Suspense } from 'react'
async function Reviews() {
const res = await fetch('https://api.example.com/reviews') // slow
const reviews = await res.json()
return <ul>{reviews.map((r) => <li key={r.id}>⭐ {r.text}</li>)}</ul>
}
export default function Home() {
return (
<main>
<h1>Learn coding with EduSite</h1> {/* instant */}
<Suspense fallback={<p>Loading reviews…</p>}>
<Reviews /> {/* streams later */}
</Suspense>
</main>
)
}error.jsx — crashes पकड़ना
JSX – app/error.jsx
// app/error.jsx (from the EduSite project)
'use client' // error boundaries must be Client Components
export default function Error({ error, reset }) {
return (
<div className="container section" style={{ textAlign: 'center' }}>
<h1>Something went wrong</h1>
<p className="lead">Please try again. If the problem continues, contact us.</p>
<button className="btn" onClick={() => reset()}>Try again</button>
</div>
)
}reset() segment को दोबारा render करने की कोशिश करता है — जब network call कुछ पल के लिए fail हुई हो तब काम का। सिर्फ़ टूटा हुआ segment error दिखाता है; layout का header और footer चलते रहते हैं।
global-error.jsx
JSX – app/global-error.jsx
// app/global-error.jsx — catches errors in the ROOT layout itself
'use client'
export default function GlobalError({ reset }) {
return (
<html><body>
<h1>Site is temporarily unavailable</h1>
<button onClick={() => reset()}>Reload</button>
</body></html>
)
}not-found.jsx — असली 404
JSX – app/not-found.jsx
// app/not-found.jsx (from the EduSite project)
import Link from 'next/link'
export default function NotFound() {
return (
<div className="container section" style={{ textAlign: 'center' }}>
<h1>404 – Page not found</h1>
<p className="lead">The page you are looking for does not exist or has moved.</p>
<Link href="/" className="btn">Go to home page</Link>
</div>
)
}
// Shown for unknown URLs AND whenever you call notFound()
Next.js page को कैसे wrap करता है
Component hierarchy (conceptual)
<Layout>
<ErrorBoundary fallback={<Error />}> ← error.jsx
<Suspense fallback={<Loading />}> ← loading.jsx
<ErrorBoundary fallback={<NotFound />}> ← not-found.jsx
<Page /> ← page.jsx
</ErrorBoundary>
</Suspense>
</ErrorBoundary>
</Layout>आम गलतियाँ
- error.jsx में
'use client'भूलना → build error। - error.jsx से उसी folder के layout के errors पकड़ने की उम्मीद → यह page और children पकड़ता है; layout errors parent के error.jsx या global-error.jsx में जाते हैं।
- 50 ms वाले data के लिए spinner → बेकार flicker; loading UI वहाँ use करें जहाँ data सच में slow हो।
- Dynamic
[slug]route के ऊपरloading.jsxरखना → response status 200 के साथ stream होना शुरू हो जाता है, फिर page के अंदरnotFound()404 नहीं भेज पाता। SEO pages के लिए loading.jsx उस path से बाहर रखें याdynamicParams = falseset करें।
सारांश
loading.jsx= automatic Suspense fallback; एक slow हिस्से के लिए<Suspense>।error.jsx(client) errors पकड़ता है औरreset()देता है।not-found.jsx+notFound()= असली 404 pages।
✅ Practice
Blog page में 2 second delay जोड़कर 3-card skeleton loader बनाइए। फिर जानबूझकर error throw कीजिए (throw new Error('test')) और working "Try again" button के साथ अपना error.jsx देखिए।
अक्सर पूछे जाने वाले प्रश्न (FAQ)
error.jsx Client Component क्यों होना चाहिए?
Error boundaries browser पर React state से errors पकड़ते हैं और reset() retry देते हैं, इसलिए file 'use client' से शुरू होनी चाहिए।
क्या loading.jsx SEO खराब करता है?
नहीं। Next.js HTML stream करता है; search engines को उसी response में final content मिलता है। Loading UI सिर्फ़ slow connection वाले users की मदद करता है।
loading.jsx और में क्या फ़र्क है?
loading.jsx पूरे page segment को अपने आप Suspense में wrap करता है। Manual से सिर्फ़ एक slow हिस्से का fallback दिखा सकते हैं जबकि बाकी page तुरंत दिख जाता है।
