Layout-uri, stări și navigare
Layout-uri imbricate, loading/error/not-found, Link și useRouter.
Actualizat
Ce este un layout
Un layout e UI-ul comun mai multor pagini: header, sidebar, footer. Îl scrii o dată, iar paginile se randează în locul children.
// app/blog/layout.tsx
export default function BlogLayout({ children }: LayoutProps<'/blog'>) {
return (
<div className="grid grid-cols-[200px_1fr]">
<BlogSidebar />
{children} {/* aici apare pagina curentă */}
</div>
)
}Proprietatea cea mai importantă: la navigarea între paginile copil, layout-ul nu se re-montează — state-ul lui (un input, scroll-ul sidebar-ului) rămâne. Se schimbă doar children.
Layout-urile se îmbrică
/blog/salut = app/layout.tsx → app/blog/layout.tsx → app/blog/[slug]/page.tsx.
Layout vs template — diferențe
layout.tsx |
template.tsx |
|
|---|---|---|
| La navigare între copii | păstrat, state-ul rămâne | re-montat, state resetat |
| Când | aproape mereu | animații de intrare, reset de formular la fiecare pagină |
Stările de UI ca fișiere
Next transformă fișiere speciale în componente React potrivite, automat:
| Fișier | Devine | Când apare |
|---|---|---|
loading.tsx |
<Suspense fallback> în jurul paginii |
cât se încarcă datele paginii |
error.tsx |
error boundary | o eroare aruncată în segment |
not-found.tsx |
pagină 404 | notFound() sau rută inexistentă |
global-error.tsx |
error boundary pentru layout-ul root | erori și în layout |
'use client' // error.tsx trebuie să fie Client Component
export default function Error({ error, reset }: { error: Error; reset: () => void }) {
return (
<div>
<p>Ceva n-a mers.</p>
<button onClick={reset}>Încearcă din nou</button>
</div>
)
}Ce este navigarea client-side
Cu un <a href> simplu, browserul descarcă toată pagina din nou. Cu <Link>, Next aduce doar ce s-a schimbat și actualizează pagina fără reload — layout-urile rămân, tranziția e instantă.
import Link from 'next/link'
<Link href="/blog/salut">Citește</Link><Link> face și prefetch: când linkul apare pe ecran, Next începe să încarce ruta în fundal.
Moduri de a naviga — și când
| Mod | Unde | Când |
|---|---|---|
<Link href> |
oriunde | implicit — orice navigare declanșată de un click pe link |
useRouter().push('/x') |
Client Component | după o acțiune: submit, logică condiționată |
router.refresh() |
Client Component | re-cere datele server ale paginii curente |
redirect('/login') |
Server Component, Server Action | userul nu are voie aici / după o mutație |
notFound() |
server | resursa nu există |
useRouter vine din next/navigation, nu din next/router (acela e Pages Router).
Link activ în meniu
'use client'
const pathname = usePathname()
const active = pathname === href || pathname.startsWith(href + '/')
<Link href={href} aria-current={active ? 'page' : undefined}>...</Link>Pe scurt
- Layout = UI comun, persistă la navigare; template = se re-montează.
loading,error,not-found= stări de UI declarate ca fișiere.<Link>pentru navigare fără reload + prefetch;useRouterdinnext/navigationpentru navigare din cod.