11 — Loading UI (loading.js / loading.tsx)
Výuka
Proč to existuje?
Když uživatel přechází na novou stránku nebo se načítají data ze serveru, může to chvíli trvat. Bez loading stavu by uživatel viděl prázdnou stránku nebo "zamrzlou" aplikaci — což vypadá, jako by se něco pokazilo.
Loading UI zobrazuje uživateli vizuální feedback (např. spinner, skeleton, progress bar), že se něco děje a aplikace funguje. To výrazně zlepšuje uživatelský zážitek.
Jak to funguje?
Next.js používá React Suspense pro automatické zobrazení loading stavů. Když vytvoříš soubor loading.js nebo loading.tsx ve složce, Next.js ho automaticky zobrazí, zatímco se načítá stránka nebo data.
Pravidlo:
- Vytvoř
loading.jsve složce → zobrazí se během načítání této stránky a všech podsložek - Loading komponenta obaluje
page.jspomocí Suspense
Jak probíhá načítání:
- Uživatel klikne na odkaz → Next.js začne načítat novou stránku
- Zobrazí se
loading.js→ uživatel vidí, že se něco děje - Stránka se načte →
loading.jszmizí a zobrazí se skutečný obsah
K čemu to slouží?
- Lepší UX — uživatel ví, že se stránka načítá
- Profesionální dojem — aplikace působí responsivně
- Automatické — nemusíš manuálně řídit zobrazení/skrytí loaderu
- Per-route loading — každá sekce může mít vlastní loading UI
JavaScript
// app/blog/loading.js
export default function Loading() {
return (
<div style={{ padding: '2rem', textAlign: 'center' }}>
<div className="spinner">Načítání...</div>
<p>Připravujeme obsah pro vás</p>
</div>
)
}
// app/blog/page.js
export default async function BlogPage() {
// Simulace načítání dat (např. z API)
const posts = await fetch('https://api.example.com/posts').then(r => r.json())
return (
<div>
<h1>Blog</h1>
{posts.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</article>
))}
</div>
)
}
Skeleton loading (pokročilé)
// app/products/loading.js
export default function Loading() {
return (
<div className="products-grid">
{[1, 2, 3, 4].map(i => (
<div key={i} className="skeleton-card">
<div className="skeleton-image" />
<div className="skeleton-title" />
<div className="skeleton-text" />
</div>
))}
</div>
)
}
TypeScript
// app/blog/loading.tsx
export default function Loading(): JSX.Element {
return (
<div style={{ padding: '2rem', textAlign: 'center' }}>
<div className="spinner">Načítání...</div>
<p>Připravujeme obsah pro vás</p>
</div>
)
}
// app/blog/page.tsx
interface Post {
id: number
title: string
excerpt: string
}
export default async function BlogPage(): Promise<JSX.Element> {
const posts: Post[] = await fetch('https://api.example.com/posts')
.then(r => r.json())
return (
<div>
<h1>Blog</h1>
{posts.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</article>
))}
</div>
)
}
Rozdíl JS vs TS
TypeScript přidává typy pro data (např. Post interface) a návratové typy (JSX.Element, Promise). To zajišťuje, že komponenty vracejí správný typ a data mají očekávanou strukturu.
Důležité poznámky
Kde umístit loading.js?
app/
├─ loading.js # loading pro celou aplikaci (/)
├─ page.js
├─ blog/
│ ├─ loading.js # loading pro /blog a /blog/*
│ └─ page.js
└─ dashboard/
├─ loading.js # loading pro /dashboard a /dashboard/*
└─ page.js
Vlastní spinner komponenta
// components/Spinner.js
export default function Spinner() {
return (
<div className="spinner-container">
<div className="spinner" />
<style jsx>{`
.spinner {
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
`}</style>
</div>
)
}
// app/loading.js
import Spinner from '@/components/Spinner'
export default function Loading() {
return <Spinner />
}
Tip
- Používej skeleton screens místo spinnerů — uživatel vidí aproximaci layoutu, což působí rychleji
- Loading UI by měl odpovídat designu stránky — stejné barvy, fonty
- Nezapomeň na accessibility — přidej
aria-label="Načítání obsahu"pro screen readery - Pro velmi rychlé načítání můžeš přidat malé zpoždění, aby loading neblikl (např. min 200ms)
Kvíz
Kdy se zobrazí obsah souboru loading.js?
Next.js automaticky používá loading.js jako fallback během Suspense boundary. Když se načítá stránka nebo async komponenta, Next.js zobrazí loading UI, dokud se obsah nenačte. Nepotřebuješ psát žádný kód pro zobrazení/skrytí — je to automatické.
🎯 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ě