05 — Layout komponenty (layout.js / layout.tsx)
Výuka
Proč to existuje?
Když vytváříš webovou aplikaci, mnoho stránek sdílí stejné prvky — header, footer, navigaci, sidebar. Bez layoutů bys musel tyto části kopírovat do každé stránky zvlášť. Layouty umožňují tyto části napsat jednou a sdílet mezi více stránkami.
Navíc layouty uchovávají stav komponent při navigaci — pokud máš v layoutu otevřené menu nebo komponentu s interaktivním stavem, zůstane zachovaná, když uživatel přechází mezi stránkami.
Co je layout?
Layout není stránka — layout obaluje stránky. Je to React komponenta, která přijímá children prop (to jsou stránky uvnitř) a může k nim přidat společné UI prvky.
Představ si to jako rámeček obrazu: rám (layout) zůstává stejný, ale obrázek uvnitř (page) se mění podle toho, na jaké stránce jsi.
Jak to funguje?
V Next.js existují dva typy layoutů:
1. Root layout (app/layout.js)
- Je povinný a musí obsahovat
atagy - Obaluje celou aplikaci
- Slouží pro globální prvky (hlavní navigace, footer)
2. Vnořené layouty (např. app/blog/layout.js)
- Jsou volitelné
- Obalují pouze stránky v dané složce a podsložkách
- Slouží pro sekce aplikace (např. blog se sidebar, dashboard s navigací)
K čemu to slouží?
- Lepší organizace UI — sdílené prvky (header, footer) jsou na jednom místě
- DRY princip — nepotřebuješ opakovat stejný kód
- Zachování stavu — interaktivní komponenty v layoutu zůstávají "živé" při navigaci
- Rychlé vytváření sekcí — blog sekce může mít sidebar, admin sekce může mít jinou navigaci
JavaScript
// app/layout.js (root layout)
export default function RootLayout({ children }) {
return (
<html lang="cs">
<body>
<header>
<nav>
<a href="/">Domů</a>
<a href="/blog">Blog</a>
</nav>
</header>
<main>{children}</main>
<footer>© Moje učebnice</footer>
</body>
</html>
)
}
// app/page.js (index page)
export default function Page() {
return <h1>Vítejte — Next.js App Router</h1>
}
// app/blog/layout.js (vnořený layout pro blog)
export default function BlogLayout({ children }) {
return (
<div style={{display: 'flex'}}>
<aside style={{width: 200}}>
<h3>Blog Sidebar</h3>
<ul>
<li><a href="/blog">Všechny články</a></li>
<li><a href="/blog/kategorie">Kategorie</a></li>
</ul>
</aside>
<main style={{flex: 1}}>{children}</main>
</div>
)
}
TypeScript
// app/layout.tsx (root layout)
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="cs">
<body>
<header>
<nav>
<a href="/">Domů</a>
<a href="/blog">Blog</a>
</nav>
</header>
<main>{children}</main>
<footer>© Moje učebnice</footer>
</body>
</html>
)
}
// app/page.tsx (index page)
export default function Page(): JSX.Element {
return <h1>Vítejte — Next.js App Router</h1>
}
// app/blog/layout.tsx (vnořený layout pro blog)
export default function BlogLayout({ children }: { children: React.ReactNode }) {
return (
<div style={{display: 'flex'}}>
<aside style={{width: 200}}>
<h3>Blog Sidebar</h3>
<ul>
<li><a href="/blog">Všechny články</a></li>
<li><a href="/blog/kategorie">Kategorie</a></li>
</ul>
</aside>
<main style={{flex: 1}}>{children}</main>
</div>
)
}
Rozdíl JS vs TS
TypeScript zajišťuje typovou kontrolu pro children, params a další props (např. ({ children }: { children: React.ReactNode })). To pomáhá vyhnout se chybám při refaktoringu — pokud změníš strukturu props, TypeScript ti ihned ukáže, kde je potřeba aktualizovat kód.
Důležité poznámky
use client direktiva
Layouty jsou ve výchozím nastavení server components. Pokud potřebuješ klientskou logiku (state, event handlery, hooks), označ soubor direktivou "use client" na začátku:
"use client"
import { useState } from 'react'
export default function InteractiveLayout({ children }) {
const [isOpen, setIsOpen] = useState(false)
// ... klientská logika
}
Tip
- Root
layoutmusí obsahovatatagy — je to jediné místo, kde je můžeš použít - Pro navigaci používej
Linkznext/linkmísto(rychlejší client-side transitions) - Layouty můžeš vnořovat do sebe libovolně hluboko — každý layout obaluje své
children - Začni s jednoduchou strukturou a přidávej vnořené layouty postupně podle potřeby
Přehled vnořených layoutů — ASCII diagram
Příklad, jak se mohou vnořené layouty a stránky navzájem vztahovat:
app/
├─ layout.tsx # root layout (html + body + hlavní navigace)
├─ page.tsx # → /
├─ blog/
│ ├─ layout.tsx # blog layout (sidebar s kategoriemi)
│ ├─ page.tsx # → /blog
│ └─ [slug]/
│ └─ page.tsx # → /blog/:slug
└─ dashboard/
├─ layout.tsx # dashboard layout (auth wrapper + admin nav)
├─ page.tsx # → /dashboard
└─ analytics/
├─ layout.tsx # nested layout pro analytics (grafy toolbar)
└─ page.tsx # → /dashboard/analytics
Jak se vnořování projevuje:
- Když navštívíš
/blog/prvni-clanek, Next.js vykreslí:- Root layout (html + body + hlavní navigace)
- Blog layout (sidebar)
- Page pro článek
Vnořené layouty přidávají nebo mění části UI pouze pro daný segment, a stav v root layoutu zůstává zachován při navigaci mezi podstránkami.
Kvíz
Který soubor sdílí UI mezi stránkami v rámci jedné sekce aplikace?
layout.js obalí všechny stránky v daném segmentu (složce) a ukládá sdílené části UI jako header, footer nebo sidebar. Na rozdíl od page.js, který je specifický pro jednu URL, layout se aplikuje na celou sekci aplikace.
🎯 Závěrečný projekt
Po dokončení všech 8 dílů vytvoříte jednoduchou Todо aplikaci v čistém JavaScriptu. Naučíte se, jak aplikovat vše, co jste se naučili, na reálný projekt.
Zobrazit podrobnosti projektu →Informace o seriálu
Obtížnost
Délka
Cca 480 minut
Počet videí
8 videí + projekty
Certifikát
Po dokončení obdržíte certifikát
Lekce v této sekci
- 01 — Co je Next.js
- 02 — Vytvoření projektu
- 03 — Struktura projektu (app/)
- 04 — Page komponenty (page.js / page.tsx)
- 05 — Layout komponenty (layout.js / layout.tsx)
- 06 — File-based routing
- 07 — Dynamické routy ([id]/page.js)
- 08 — Link komponenta (navigace)
- 09 — Image komponenta (next/image)
- 10 — Metadata (title, description, Open Graph)
- 11 — Loading UI (loading.js / loading.tsx)
- 12 — Error handling (error.js / error.tsx)
- 13 — Not Found (not-found.js / not-found.tsx)
Struktura lekcí (souborový strom)
- 1.1 Úvod do JavaScriptu a TypeScriptu
- 1.2 Nastavení prostředí
- 1.3 První program
- 1.4 Proměnné: var, let, const
- 1.5 Datové typy - přehled
- 1.6 String (řetězce)
- 1.7 Number (čísla)
- 1.8 Boolean (pravda/nepravda)
- 1.9 Null a Undefined
- 1.10 Type Inference vs Annotations
- 1.11 Aritmetické operátory
- 1.12 Porovnávací operátory
- 1.13 Logické operátory
- 1.14 Komentáře
- 1.15 Console metody
- 03.01 Deklarace funkce
- 03.02 Function Expression
- 03.03 Arrow Functions
- 03.04 Parametry a argumenty
- 03.05 Return hodnoty
- 03.06 Výchozí parametry
- 03.07 Rest parametry
- 03.08 Co je Scope
- 03.09 Lexikální Scope
- 03.10 Řetězec Scope
- 03.11 Globální Scope
- 03.12 Životní Cyklus Proměnných
- 03.13 Omezení Scope
- 03.14 Použití Closures
- 03.15 Callback funkce
- 03.16 Higher-order Functions
- 03.17 IIFE
- 03.18 Void funkce
- 03.19 Rekurze
- v přípravě
- v přípravě
- v přípravě
- v přípravě
- 01 — Co je Next.js
- 02 — Vytvoření projektu
- 03 — Struktura projektu (app/)
- 04 — Page komponenty (page.js / page.tsx)
- 05 — Layout komponenty (layout.js / layout.tsx)
- 06 — File-based routing
- 07 — Dynamické routy ([id]/page.js)
- 08 — Link komponenta (navigace)
- 09 — Image komponenta (next/image)
- 10 — Metadata (title, description, Open Graph)
- 11 — Loading UI (loading.js / loading.tsx)
- 12 — Error handling (error.js / error.tsx)
- 13 — Not Found (not-found.js / not-found.tsx)
- v přípravě
- v přípravě
- v přípravě