Prozkoumejte klíčové navigační vzory s React Router v6. Naučte se deklarativní, dynamické a programatické routování, vnořené trasy a strategie načítání dat pro tvorbu robustních a uživatelsky přívětivých webových aplikací.
React Router v6: Zvládnutí navigačních vzorů pro moderní webové aplikace
React Router v6 je výkonná a flexibilní knihovna pro routování v React aplikacích. Umožňuje vytvářet jednostránkové aplikace (SPA) s plynulým uživatelským zážitkem díky správě navigace bez nutnosti znovunačítání celé stránky. Tento článek se ponoří do klíčových navigačních vzorů s použitím React Router v6 a poskytne vám znalosti a příklady pro tvorbu robustních a uživatelsky přívětivých webových aplikací.
Pochopení základních konceptů React Router v6
Než se ponoříme do konkrétních vzorů, zopakujme si některé základní koncepty:
- Deklarativní routování: React Router používá deklarativní přístup, kde definujete své trasy jako React komponenty. Díky tomu je logika routování přehledná a snadno udržovatelná.
- Komponenty: Mezi základní komponenty patří
BrowserRouter
,HashRouter
,MemoryRouter
,Routes
aRoute
. - Hooky: React Router poskytuje hooky jako
useNavigate
,useLocation
,useParams
auseRoutes
pro přístup k informacím o routování a manipulaci s navigací.
1. Deklarativní routování s <Routes>
a <Route>
Základem React Router v6 je deklarativní routování. Své trasy definujete pomocí komponent <Routes>
a <Route>
. Komponenta <Routes>
funguje jako kontejner pro vaše trasy a komponenta <Route>
definuje konkrétní trasu a komponentu, která se má vykreslit, když tato trasa odpovídá aktuální URL.
Příklad: Základní konfigurace tras
Zde je základní příklad nastavení tras pro jednoduchou aplikaci:
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import Contact from "./pages/Contact";
function App() {
return (
} />
} />
} />
);
}
export default App;
V tomto příkladu definujeme tři trasy:
/
: Vykreslí komponentuHome
./about
: Vykreslí komponentuAbout
./contact
: Vykreslí komponentuContact
.
Komponenta BrowserRouter
umožňuje routování založené na historii prohlížeče. React Router porovná aktuální URL s definovanými trasami a vykreslí odpovídající komponentu.
2. Dynamické trasy s URL parametry
Dynamické trasy vám umožňují vytvářet trasy, které mohou zpracovávat různé hodnoty v URL. To je užitečné pro zobrazování obsahu na základě jedinečného identifikátoru, jako je ID produktu nebo ID uživatele. React Router v6 používá symbol :
k definování URL parametrů.
Příklad: Zobrazení detailů produktu
Řekněme, že máte e-commerce aplikaci a chcete zobrazit detaily každého produktu na základě jeho ID. Můžete definovat dynamickou trasu takto:
import { BrowserRouter, Routes, Route, useParams } from "react-router-dom";
function ProductDetails() {
const { productId } = useParams();
// Načtení detailů produktu na základě productId
// ...
return (
Detaily produktu
ID produktu: {productId}
{/* Zde zobrazit detaily produktu */}
);
}
function App() {
return (
} />
);
}
export default App;
V tomto příkladu:
/products/:productId
definuje dynamickou trasu, kde:productId
je URL parametr.- Hook
useParams
se používá pro přístup k hodnotě parametruproductId
uvnitř komponentyProductDetails
. - Poté můžete použít
productId
k načtení odpovídajících detailů produktu z vašeho zdroje dat.
Příklad internacionalizace: Zpracování jazykových kódů
Pro vícejazyčný web můžete použít dynamickou trasu pro zpracování jazykových kódů:
} />
Tato trasa by odpovídala URL jako /en/about
, /fr/about
a /cs/about
. Parametr lang
lze poté použít k načtení příslušných jazykových zdrojů.
3. Programatická navigace s useNavigate
Zatímco deklarativní routování je skvělé pro statické odkazy, často potřebujete navigovat programaticky na základě akcí uživatele nebo logiky aplikace. React Router v6 pro tento účel poskytuje hook useNavigate
. useNavigate
vrací funkci, která vám umožňuje navigovat na různé trasy.
Příklad: Přesměrování po odeslání formuláře
Řekněme, že máte formulář a po jeho úspěšném odeslání chcete uživatele přesměrovat na stránku s potvrzením:
import { useNavigate } from "react-router-dom";
function MyForm() {
const navigate = useNavigate();
const handleSubmit = async (event) => {
event.preventDefault();
// Odeslání dat formuláře
// ...
// Přesměrování na stránku s potvrzením po úspěšném odeslání
navigate("/success");
};
return (
);
}
export default MyForm;
V tomto příkladu:
- Používáme hook
useNavigate
k získání funkcenavigate
. - Po úspěšném odeslání formuláře voláme
navigate("/success")
, abychom uživatele přesměrovali na trasu/success
.
Předávání stavu během navigace
Můžete také předat stav spolu s navigací pomocí druhého argumentu funkce navigate
:
navigate("/confirmation", { state: { orderId: "12345" } });
To vám umožní předat data cílové komponentě, ke které lze přistupovat pomocí hooku useLocation
.
4. Vnořené trasy a layouty
Vnořené trasy umožňují vytvářet hierarchické struktury routování, kde je jedna trasa vnořena do druhé. To je užitečné pro organizaci složitých aplikací s více úrovněmi navigace. Pomáhá to vytvářet layouty, kde jsou určité prvky uživatelského rozhraní konzistentně přítomny v celé sekci aplikace.
Příklad: Sekce uživatelského profilu
Řekněme, že máte sekci uživatelského profilu s vnořenými trasami pro zobrazení informací o profilu, nastavení a objednávek uživatele:
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
function Profile() {
return (
Uživatelský profil
-
Informace o profilu
-
Nastavení
-
Objednávky
} />
} />
} />
);
}
function ProfileInformation() {
return Komponenta s informacemi o profilu
;
}
function Settings() {
return Komponenta nastavení
;
}
function Orders() {
return Komponenta objednávek
;
}
function App() {
return (
} />
);
}
export default App;
V tomto příkladu:
- Trasa
/profile/*
odpovídá jakékoli URL, která začíná/profile
. - Komponenta
Profile
vykresluje navigační menu a komponentu<Routes>
pro zpracování vnořených tras. - Vnořené trasy definují komponenty, které se mají vykreslit pro
/profile/info
,/profile/settings
a/profile/orders
.
*
v rodičovské trase je klíčová; znamená, že rodičovská trasa by měla odpovídat jakékoli podřazené cestě, což umožňuje správné porovnání vnořených tras v rámci komponenty Profile
.
5. Zpracování chyb "Nenalezeno" (404)
Je nezbytné ošetřit případy, kdy uživatel přejde na trasu, která neexistuje. React Router v6 to usnadňuje pomocí záchytné trasy (catch-all route).
Příklad: Implementace stránky 404
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
function NotFound() {
return (
404 - Nenalezeno
Stránka, kterou hledáte, neexistuje.
Zpět na domovskou stránku
);
}
function App() {
return (
} />
} />
} />
);
}
V tomto příkladu:
- Trasa
<Route path="*" element={<NotFound />} />
je záchytná trasa, která odpovídá jakékoli URL, která neodpovídá žádné z ostatních definovaných tras. - Je důležité umístit tuto trasu na konec komponenty
<Routes>
, aby se uplatnila pouze v případě, že žádná jiná trasa neodpovídá.
6. Strategie načítání dat s React Router v6
React Router v6 neobsahuje vestavěné mechanismy pro načítání dat jako jeho předchůdce (React Router v5 s `useRouteMatch`). Poskytuje však nástroje pro efektivní implementaci různých strategií načítání dat.
Možnost 1: Načítání dat v komponentách
Nejjednodušším přístupem je načítat data přímo v komponentě, která vykresluje danou trasu. Můžete použít hook useEffect
k načtení dat při připojení komponenty (mount) nebo při změně URL parametrů.
import { useParams } from "react-router-dom";
import { useEffect, useState } from "react";
function ProductDetails() {
const { productId } = useParams();
const [product, setProduct] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchProduct() {
try {
const response = await fetch(`/api/products/${productId}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setProduct(data);
setLoading(false);
} catch (e) {
setError(e);
setLoading(false);
}
}
fetchProduct();
}, [productId]);
if (loading) return Načítání...
;
if (error) return Chyba: {error.message}
;
if (!product) return Produkt nenalezen
;
return (
{product.name}
{product.description}
);
}
export default ProductDetails;
Tento přístup je přímočarý, ale může vést k duplikaci kódu, pokud potřebujete načítat data ve více komponentách. Je také méně efektivní, protože načítání dat začíná až po připojení komponenty.
Možnost 2: Použití vlastního hooku pro načítání dat
Pro snížení duplikace kódu můžete vytvořit vlastní hook, který zapouzdří logiku načítání dat. Tento hook lze poté znovu použít ve více komponentách.
import { useState, useEffect } from "react";
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchData() {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const json = await response.json();
setData(json);
setLoading(false);
} catch (e) {
setError(e);
setLoading(false);
}
}
fetchData();
}, [url]);
return { data, loading, error };
}
export default useFetch;
Poté můžete tento hook použít ve svých komponentách:
import { useParams } from "react-router-dom";
import useFetch from "./useFetch";
function ProductDetails() {
const { productId } = useParams();
const { data: product, loading, error } = useFetch(`/api/products/${productId}`);
if (loading) return Načítání...
;
if (error) return Chyba: {error.message}
;
if (!product) return Produkt nenalezen
;
return (
{product.name}
{product.description}
);
}
export default ProductDetails;
Možnost 3: Použití routovací knihovny se schopnostmi načítání dat (TanStack Router, Remix)
Knihovny jako TanStack Router a Remix nabízejí vestavěné mechanismy pro načítání dat, které se bezproblémově integrují s routováním. Tyto knihovny často poskytují funkce jako:
- Loaders: Funkce, které se provádějí *před* vykreslením trasy, což vám umožňuje načíst data a předat je komponentě.
- Actions: Funkce, které zpracovávají odesílání formulářů a mutace dat.
Použití takové knihovny může drasticky zjednodušit načítání dat a zlepšit výkon, zejména u složitých aplikací.
Vykreslování na straně serveru (SSR) a generování statických stránek (SSG)
Pro lepší SEO a výkon při prvním načtení zvažte použití SSR nebo SSG s frameworky jako Next.js nebo Gatsby. Tyto frameworky vám umožňují načítat data na serveru nebo během sestavování (build time) a servírovat klientovi předem vykreslené HTML. Tím se eliminuje potřeba klienta načítat data při prvním načtení, což vede k rychlejšímu a pro SEO přívětivějšímu zážitku.
7. Práce s různými typy routerů
React Router v6 poskytuje různé implementace routerů pro různá prostředí a případy použití:
- BrowserRouter: Používá HTML5 history API (
pushState
,replaceState
) pro navigaci. Je to nejběžnější volba pro webové aplikace běžící v prostředí prohlížeče. - HashRouter: Používá část URL s hashem (
#
) pro navigaci. To je užitečné pro aplikace, které potřebují podporovat starší prohlížeče nebo jsou nasazeny na serverech, které nepodporují HTML5 history API. - MemoryRouter: Udržuje historii vaší "URL" v paměti (pole URL). Užitečné v prostředích jako React Native a při testování.
Vyberte si typ routeru, který nejlépe vyhovuje požadavkům a prostředí vaší aplikace.
Závěr
React Router v6 poskytuje komplexní a flexibilní řešení routování pro React aplikace. Porozuměním a aplikací navigačních vzorů probíraných v tomto článku můžete vytvářet robustní, uživatelsky přívětivé a udržovatelné webové aplikace. Od deklarativního routování s <Routes>
a <Route>
přes dynamické trasy s URL parametry, programatickou navigaci s useNavigate
až po efektivní strategie načítání dat, React Router v6 vám dává sílu vytvářet plynulé navigační zážitky pro vaše uživatele. Zvažte prozkoumání pokročilejších routovacích knihoven a SSR/SSG frameworků pro ještě větší kontrolu a optimalizaci výkonu. Nezapomeňte tyto vzory přizpůsobit specifickým požadavkům vaší aplikace a vždy upřednostňujte jasný a intuitivní uživatelský zážitek.