13 — Not Found (not-found.js / not-found.tsx)
Výuka
Proč to existuje?
Když uživatel zadá URL, která neexistuje (např. /blog/neexistujici-clanek), nebo když databáze neobsahuje požadovaný záznam, měla by aplikace zobrazit přátelskou 404 stránku místo běžné chyby nebo prázdné stránky.
Not Found stránka (404) informuje uživatele, že hledaný obsah neexistuje, a nabízí mu návrat na fungující části aplikace (např. domovská stránka, vyhledávání).
Jak to funguje?
Next.js poskytuje dva způsoby, jak zobrazit 404 stránku:
1. Automaticky — když Next.js nenajde odpovídající route
- Uživatel zadá
/neexistujici-stranka→ zobrazí se rootnot-found.js
2. Programově — pomocí funkce notFound()
- Načítáš data z databáze → záznam neexistuje → zavoláš
notFound() - Next.js zobrazí nejbližší
not-found.jsv adresářové struktuře
Kde umístit not-found.js:
app/
├─ not-found.js # globální 404 stránka
├─ page.js
└─ blog/
├─ not-found.js # 404 specifická pro blog sekci
└─ [slug]/
└─ page.js
K čemu to slouží?
- Lepší UX — uživatel ví, že stránka neexistuje (není to chyba aplikace)
- SEO — správná HTTP 404 odpověď pro vyhledávače
- Navigace zpět — odkaz na domovskou stránku nebo vyhledávání
- Branding — možnost udržet design a identitu aplikace i na chybové stránce
JavaScript
// app/not-found.js (globální 404)
import Link from 'next/link'
export default function NotFound() {
return (
<div style={{ textAlign: 'center', padding: '4rem 2rem' }}>
<h1 style={{ fontSize: '4rem', margin: '0' }}>404</h1>
<h2>Stránka nenalezena</h2>
<p style={{ color: '#666', marginBottom: '2rem' }}>
Omlouváme se, ale stránka, kterou hledáte, neexistuje.
</p>
<Link href="/" style={{ color: '#0070f3', textDecoration: 'none' }}>
← Zpět na domovskou stránku
</Link>
</div>
)
}
Programové vyvolání 404
// app/blog/[slug]/page.js
import { notFound } from 'next/navigation'
export default async function BlogPost({ params }) {
const post = await fetch(`https://api.example.com/posts/${params.slug}`)
.then(res => res.ok ? res.json() : null)
// Pokud článek neexistuje, zobraz 404
if (!post) {
notFound()
}
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
)
}
Vlastní 404 pro sekci
// app/blog/not-found.js
import Link from 'next/link'
export default function BlogNotFound() {
return (
<div style={{ textAlign: 'center', padding: '2rem' }}>
<h2>Článek nenalezen</h2>
<p>Tento článek neexistuje nebo byl odstraněn.</p>
<Link href="/blog">← Zpět na seznam článků</Link>
</div>
)
}
TypeScript
// app/not-found.tsx (globální 404)
import Link from 'next/link'
export default function NotFound(): JSX.Element {
return (
<div style={{ textAlign: 'center', padding: '4rem 2rem' }}>
<h1 style={{ fontSize: '4rem', margin: '0' }}>404</h1>
<h2>Stránka nenalezena</h2>
<p style={{ color: '#666', marginBottom: '2rem' }}>
Omlouváme se, ale stránka, kterou hledáte, neexistuje.
</p>
<Link href="/" style={{ color: '#0070f3', textDecoration: 'none' }}>
← Zpět na domovskou stránku
</Link>
</div>
)
}
Programové vyvolání s typy
// app/blog/[slug]/page.tsx
import { notFound } from 'next/navigation'
interface Post {
id: number
slug: string
title: string
content: string
}
interface PageProps {
params: { slug: string }
}
export default async function BlogPost({ params }: PageProps): Promise<JSX.Element> {
const response = await fetch(`https://api.example.com/posts/${params.slug}`)
if (!response.ok) {
notFound() // Vyvolá nejbližší not-found.tsx
}
const post: Post = await response.json()
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
)
}
Typovaná 404 s vyhledáváním
// app/products/not-found.tsx
import Link from 'next/link'
export default function ProductNotFound(): JSX.Element {
return (
<div style={{ maxWidth: '600px', margin: '4rem auto', textAlign: 'center' }}>
<h2>Produkt nenalezen</h2>
<p>Tento produkt neexistuje nebo není skladem.</p>
<div style={{ marginTop: '2rem', display: 'flex', gap: '1rem', justifyContent: 'center' }}>
<Link href="/products">
Procházet produkty
</Link>
<Link href="/products/search">
Vyhledat produkt
</Link>
</div>
</div>
)
}
Rozdíl JS vs TS
TypeScript přidává typy pro params a searchParams v page komponentách, což zajišťuje, že pracuješ se správnými parametry URL. Také typuje návratové hodnoty komponent (JSX.Element) a datové struktury (např. Post interface).
Důležité poznámky
Funkce notFound()
import { notFound } from 'next/navigation'
// Použití
if (!data) {
notFound() // Vyvolá nejbližší not-found.js/tsx v adresářové struktuře
}
Kde to použít:
- Když databázový záznam neexistuje
- Když uživatel nemá oprávnění (alternativně můžeš použít custom error)
- Když API vrátí 404
Hierarchie not-found souborů
app/
├─ not-found.js # Globální 404 (fallback)
├─ products/
│ ├─ not-found.js # 404 pro /products/*
│ └─ [id]/page.js # Pokud zavolá notFound(), použije products/not-found.js
└─ blog/
├─ not-found.js # 404 pro /blog/*
└─ [slug]/page.js # Pokud zavolá notFound(), použije blog/not-found.js
Priorita: Next.js použije nejbližší not-found.js v adresářovém stromu směrem nahoru.
Metadata pro 404
// app/not-found.tsx
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: '404 - Stránka nenalezena',
description: 'Tato stránka neexistuje'
}
export default function NotFound() {
// ...
}
Tip
- Užitečné odkazy — nabídni uživateli cestu zpět (domů, vyhledávání, kontakt)
- Zachovej design — 404 stránka by měla odpovídat zbytku aplikace (layout, barvy)
- SEO — Next.js automaticky vrací HTTP 404 status code
- Logování — v produkci můžeš logovat 404 (trackovat rozbité odkazy)
- Humor — můžeš použít vtipnou hlášku nebo obrázek (ale zůstaň profesionální)
- Validace před fetchem — ověř parametry před načítáním dat (např. ID musí být číslo)
Příklad s validací
export default async function ProductPage({ params }: PageProps) {
const id = parseInt(params.id)
// Validace: pokud ID není číslo, zobraz 404
if (isNaN(id) || id <= 0) {
notFound()
}
const product = await getProduct(id)
if (!product) {
notFound()
}
return <ProductDetail product={product} />
}
Kvíz
Kdy se zobrazí obsah souboru not-found.js?
Not Found stránka se zobrazí dvěma způsoby: (1) Automaticky — když uživatel navštíví URL, která neodpovídá žádné route v aplikaci. Next.js automaticky zobrazí nejbližší not-found.js. (2) Programově — když v kódu zavoláš notFound() funkci (např. když záznam v databázi neexistuje). Chyba 500 se řeší pomocí error.js, ne not-found.js.
Not Found stránka se zobrazí dvěma způsoby: (1) Automaticky — když uživatel navštíví URL, která neodpovídá žádné route v aplikaci. Next.js automaticky zobrazí nejbližší not-found.js. (2) Programově — když v kódu zavoláš notFound() funkci (např. když záznam v databázi neexistuje). Chyba 500 se řeší pomocí error.js, ne not-found.js.
🎯 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ě