Layouts, states and navigation
Nested layouts, loading/error/not-found, Link and useRouter.
Updated
What a layout is
A layout is the UI shared by several pages: a header, a sidebar, a footer. You write it once, and the pages render in place of children.
// app/blog/layout.tsx
export default function BlogLayout({ children }: LayoutProps<'/blog'>) {
return (
<div className="grid grid-cols-[200px_1fr]">
<BlogSidebar />
{children} {/* the current page shows up here */}
</div>
)
}The most important property: when you navigate between child pages, the layout doesn't remount — its state (an input, the sidebar's scroll) stays. Only children changes.
Layouts nest
/blog/hello = app/layout.tsx → app/blog/layout.tsx → app/blog/[slug]/page.tsx.
Layout vs template — the differences
layout.tsx |
template.tsx |
|
|---|---|---|
| When navigating between children | kept, the state stays | remounted, the state resets |
| When | almost always | entrance animations, resetting a form on every page |
UI states as files
Next automatically turns special files into the right React components:
| File | Becomes | When it shows |
|---|---|---|
loading.tsx |
a <Suspense fallback> around the page |
while the page's data loads |
error.tsx |
an error boundary | an error thrown in the segment |
not-found.tsx |
a 404 page | notFound() or a route that doesn't exist |
global-error.tsx |
an error boundary for the root layout | errors in the layout too |
'use client' // error.tsx must be a Client Component
export default function Error({ error, reset }: { error: Error; reset: () => void }) {
return (
<div>
<p>Something went wrong.</p>
<button onClick={reset}>Try again</button>
</div>
)
}What client-side navigation is
With a plain <a href>, the browser downloads the whole page again. With <Link>, Next fetches only what changed and updates the page without a reload — the layouts stay, the transition is instant.
import Link from 'next/link'
<Link href="/blog/hello">Read</Link><Link> also prefetches: when the link appears on screen, Next starts loading the route in the background.
Ways to navigate — and when
| Way | Where | When |
|---|---|---|
<Link href> |
anywhere | the default — any navigation triggered by clicking a link |
useRouter().push('/x') |
a Client Component | after an action: a submit, conditional logic |
router.refresh() |
a Client Component | refetches the current page's server data |
redirect('/login') |
a Server Component, a Server Action | the user isn't allowed here / after a mutation |
notFound() |
the server | the resource doesn't exist |
useRouter comes from next/navigation, not from next/router (that's the Pages Router).
The active link in a menu
'use client'
const pathname = usePathname()
const active = pathname === href || pathname.startsWith(href + '/')
<Link href={href} aria-current={active ? 'page' : undefined}>...</Link>Summary
- A layout = shared UI, persists across navigation; a template = remounts.
loading,error,not-found= UI states declared as files.<Link>for navigation without a reload + prefetching;useRouterfromnext/navigationfor navigating from code.