12 — Error handling (error.js / error.tsx)
Výuka
Proč to existuje?
V každé aplikaci můžou nastat chyby — server neodpoví, databáze není dostupná, uživatel nemá oprávnění, nebo prostě chyba v kódu. Bez ošetření chyb by aplikace "spadla" a uživatel by viděl prázdnou stránku nebo technickou chybovou hlášku.
Error handling umožňuje zobrazit uživatelsky přívětivou chybovou stránku a nabídnout možnost zotavení (např. tlačítko "Zkusit znovu").
Jak to funguje?
Next.js používá React Error Boundaries pro zachycení chyb. Když vytvoříš soubor error.js nebo error.tsx ve složce, automaticky obalí stránky v této složce error boundary.
Důležité:
error.jsmusí být client component (začíná"use client")- Zachytává chyby v
page.jsa vnořených komponentách - Nezachytává chyby v
layout.js(na to sloužíglobal-error.jsv root)
Jak probíhá zpracování chyby:
- Nastane chyba v page nebo komponentě
- Next.js zachytí chybu pomocí error boundary
- Zobrazí se
error.jsmísto původní stránky - Uživatel může zkusit akci znovu (pomocí
reset()funkce)
K čemu to slouží?
- Lepší UX — uživatel vidí přátelskou hlášku místo technické chyby
- Izolace chyb — chyba v jedné sekci nezničí celou aplikaci
- Možnost zotavení — tlačítko "Zkusit znovu" může problém vyřešit
- Per-route errors — každá sekce může mít vlastní error handling
JavaScript
// app/blog/error.js
"use client" // Error komponenty MUSÍ být client components!
export default function Error({ error, reset }) {
return (
<div style={{ padding: '2rem', textAlign: 'center' }}>
<h2>Něco se pokazilo!</h2>
<p style={{ color: '#666' }}>
{error.message || 'Nepodařilo se načíst obsah'}
</p>
<button
onClick={() => reset()}
style={{
padding: '0.5rem 1rem',
marginTop: '1rem',
cursor: 'pointer'
}}
>
Zkusit znovu
</button>
</div>
)
}
Příklad stránky, která může vyhodit chybu
// app/blog/page.js
export default async function BlogPage() {
// Pokud API selže, error.js zachytí chybu
const posts = await fetch('https://api.example.com/posts', {
// Pokud server neodpoví, vyhodí se chyba
cache: 'no-store'
}).then(res => {
if (!res.ok) throw new Error('Nepodařilo se načíst články')
return res.json()
})
return (
<div>
<h1>Blog</h1>
{posts.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
</article>
))}
</div>
)
}
TypeScript
// app/blog/error.tsx
"use client"
interface ErrorProps {
error: Error & { digest?: string }
reset: () => void
}
export default function Error({ error, reset }: ErrorProps): JSX.Element {
return (
<div style={{ padding: '2rem', textAlign: 'center' }}>
<h2>Něco se pokazilo!</h2>
<p style={{ color: '#666' }}>
{error.message || 'Nepodařilo se načíst obsah'}
</p>
<details style={{ marginTop: '1rem', textAlign: 'left' }}>
<summary>Technické detaily</summary>
<pre style={{ fontSize: '0.875rem', color: '#999' }}>
{error.stack}
</pre>
</details>
<button
onClick={() => reset()}
style={{
padding: '0.5rem 1rem',
marginTop: '1rem',
cursor: 'pointer'
}}
>
Zkusit znovu
</button>
</div>
)
}
Typovaný příklad s fetch
// app/blog/page.tsx
interface Post {
id: number
title: string
content: string
}
export default async function BlogPage(): Promise<JSX.Element> {
const response = await fetch('https://api.example.com/posts', {
cache: 'no-store'
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const posts: Post[] = await response.json()
return (
<div>
<h1>Blog</h1>
{posts.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
</article>
))}
</div>
)
}
Rozdíl JS vs TS
TypeScript přidává typy pro error prop (včetně volitelného digest pro produkční error tracking) a reset funkci. To zajišťuje, že error komponenta dostává správné props a můžeš bezpečně přistupovat k vlastnostem chyby.
Důležité poznámky
Props error komponenty
{
error: Error & { digest?: string } // Samotná chyba + digest pro tracking
reset: () => void // Funkce pro znovunačtení
}
error.message— zpráva o chyběerror.stack— stack trace (užitečné pro debugging)error.digest— unikátní hash (v produkci, pro error tracking služby)reset()— funkce, která znovu vykreslí segment (zkusí načíst znovu)
Struktura error souborů
app/
├─ error.js # zachytává chyby v celé aplikaci
├─ global-error.js # zachytává chyby v root layoutu
├─ page.js
├─ blog/
│ ├─ error.js # zachytává chyby jen v /blog sekci
│ └─ page.js
└─ dashboard/
├─ error.js # zachytává chyby jen v /dashboard sekci
└─ page.js
Global error handler
Pro zachycení chyb v root layoutu vytvoř global-error.js:
// app/global-error.js
"use client"
export default function GlobalError({ error, reset }) {
return (
<html>
<body>
<h2>Něco se hodně pokazilo!</h2>
<button onClick={() => reset()}>Zkusit znovu</button>
</body>
</html>
)
}
Pozor: global-error.js musí obsahovat vlastní a tagy!
Tip
- Vždy začni s
"use client"— error komponenty jsou klientské - Používej
reset()pro obnovení — často to chybu vyřeší (např. dočasný výpadek API) - V produkci nezobrazuj stack trace uživateli — je to bezpečnostní riziko
- Pro error tracking používej služby jako Sentry (použij
error.digest) - Testy chyb: v development mode zkus záměrně vyhodit
throw new Error("test")
Kvíz
Proč musí error.js komponenta začínat direktivou "use client"?
Error komponenty v Next.js používají React Error Boundaries, které vyžadují hooks jako getDerivedStateFromError a lifecycle metody dostupné pouze v client components. Proto musí každý error.js soubor začínat "use client" direktivou. Navíc funkce reset() je interaktivní (event handler), což také vyžaduje klientský kód.
🎯 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ě