Udforsk essentielle navigationsmønstre med React Router v6. Lær deklarativ routing, dynamiske ruter, programmatisk navigation, indlejrede ruter og dataindlæsningsstrategier for at bygge robuste og brugervenlige webapplikationer.
React Router v6: Mestring af Navigationsmønstre for Moderne Webapps
React Router v6 er et kraftfuldt og fleksibelt routing-bibliotek for React-applikationer. Det giver dig mulighed for at oprette single-page applications (SPAs) med en problemfri brugeroplevelse ved at håndtere navigation uden fulde genindlæsninger af siden. Denne blogpost vil dykke ned i essentielle navigationsmønstre ved hjælp af React Router v6 og give dig viden og eksempler til at bygge robuste og brugervenlige webapplikationer.
Forståelse af React Router v6's Kernekoncepter
Før vi dykker ned i specifikke mønstre, lad os gennemgå nogle grundlæggende koncepter:
- Deklarativ Routing: React Router bruger en deklarativ tilgang, hvor du definerer dine ruter som React-komponenter. Dette gør din routing-logik klar og vedligeholdelsesvenlig.
- Komponenter: Kernekomponenterne inkluderer
BrowserRouter
,HashRouter
,MemoryRouter
,Routes
ogRoute
. - Hooks: React Router tilbyder hooks som
useNavigate
,useLocation
,useParams
oguseRoutes
for at få adgang til routing-information og manipulere navigationen.
1. Deklarativ Routing med <Routes>
og <Route>
Fundamentet i React Router v6 ligger i deklarativ routing. Du definerer dine ruter ved hjælp af <Routes>
og <Route>
komponenterne. <Routes>
komponenten fungerer som en container for dine ruter, og <Route>
komponenten definerer en specifik rute og den komponent, der skal gengives, når den rute matcher den nuværende URL.
Eksempel: Grundlæggende Rutekonfiguration
Her er et grundlæggende eksempel på opsætning af ruter for en simpel applikation:
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;
I dette eksempel definerer vi tre ruter:
/
: GengiverHome
-komponenten./about
: GengiverAbout
-komponenten./contact
: GengiverContact
-komponenten.
BrowserRouter
-komponenten muliggør browserhistorik-baseret routing. React Router matcher den nuværende URL mod de definerede ruter og gengiver den tilsvarende komponent.
2. Dynamiske Ruter med URL-parametre
Dynamiske ruter giver dig mulighed for at oprette ruter, der kan håndtere forskellige værdier i URL'en. Dette er nyttigt til at vise indhold baseret på en unik identifikator, såsom et produkt-ID eller et bruger-ID. React Router v6 bruger :
symbolet til at definere URL-parametre.
Eksempel: Visning af Produktdetaljer
Lad os sige, du har en e-handelsapplikation og ønsker at vise detaljer for hvert produkt baseret på dets ID. Du kan definere en dynamisk rute som denne:
import { BrowserRouter, Routes, Route, useParams } from "react-router-dom";
function ProductDetails() {
const { productId } = useParams();
// Hent produktdetaljer baseret på productId
// ...
return (
Produktdetaljer
Produkt ID: {productId}
{/* Vis produktdetaljer her */}
);
}
function App() {
return (
} />
);
}
export default App;
I dette eksempel:
/products/:productId
definerer en dynamisk rute, hvor:productId
er en URL-parameter.useParams
-hooket bruges til at få adgang til værdien afproductId
-parameteren inden iProductDetails
-komponenten.- Du kan derefter bruge
productId
til at hente de tilsvarende produktdetaljer fra din datakilde.
Eksempel på Internationalisering: Håndtering af Sprogkoder
For en flersproget hjemmeside kan du bruge en dynamisk rute til at håndtere sprogkoder:
} />
Denne rute ville matche URL'er som /en/about
, /fr/about
og /es/about
. lang
-parameteren kan derefter bruges til at indlæse de relevante sprogressourcer.
3. Programmatisk Navigation med useNavigate
Mens deklarativ routing er fantastisk til statiske links, har du ofte brug for at navigere programmatisk baseret på brugerhandlinger eller applikationslogik. React Router v6 tilbyder useNavigate
-hooket til dette formål. useNavigate
returnerer en funktion, der giver dig mulighed for at navigere til forskellige ruter.
Eksempel: Omdirigering efter Formularindsendelse
Lad os sige, du har en formularindsendelse og ønsker at omdirigere brugeren til en succes-side, efter at formularen er blevet indsendt succesfuldt:
import { useNavigate } from "react-router-dom";
function MyForm() {
const navigate = useNavigate();
const handleSubmit = async (event) => {
event.preventDefault();
// Indsend formulardata
// ...
// Omdiriger til succes-siden efter succesfuld indsendelse
navigate("/success");
};
return (
);
}
export default MyForm;
I dette eksempel:
- Vi bruger
useNavigate
-hooket til at fånavigate
-funktionen. - Efter formularen er indsendt succesfuldt, kalder vi
navigate("/success")
for at omdirigere brugeren til/success
-ruten.
Overførsel af State under Navigation
Du kan også sende state med under navigationen ved hjælp af det andet argument til navigate
:
navigate("/confirmation", { state: { orderId: "12345" } });
Dette giver dig mulighed for at sende data til målkomponenten, som kan tilgås ved hjælp af useLocation
-hooket.
4. Indlejrede Ruter og Layouts
Indlejrede ruter giver dig mulighed for at oprette hierarkiske routing-strukturer, hvor en rute er indlejret i en anden. Dette er nyttigt til at organisere komplekse applikationer med flere navigationsniveauer. Dette hjælper med at skabe layouts, hvor visse UI-elementer er konsekvent til stede på tværs af en sektion af applikationen.
Eksempel: Brugerprofilsektion
Lad os sige, du har en brugerprofilsektion med indlejrede ruter til at vise brugerens profiloplysninger, indstillinger og ordrer:
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
function Profile() {
return (
Brugerprofil
-
Profiloplysninger
-
Indstillinger
-
Ordrer
} />
} />
} />
);
}
function ProfileInformation() {
return Profiloplysninger Komponent
;
}
function Settings() {
return Indstillinger Komponent
;
}
function Orders() {
return Ordrer Komponent
;
}
function App() {
return (
} />
);
}
export default App;
I dette eksempel:
/profile/*
-ruten matcher enhver URL, der starter med/profile
.Profile
-komponenten gengiver en navigationsmenu og en<Routes>
-komponent til at håndtere de indlejrede ruter.- De indlejrede ruter definerer de komponenter, der skal gengives for
/profile/info
,/profile/settings
og/profile/orders
.
*
i den overordnede rute er afgørende; det betyder, at den overordnede rute skal matche enhver understi, hvilket giver de indlejrede ruter mulighed for at blive korrekt matchet inden i Profile
-komponenten.
5. Håndtering af "Ikke Fundet" (404) Fejl
Det er vigtigt at håndtere tilfælde, hvor brugeren navigerer til en rute, der ikke eksisterer. React Router v6 gør dette let med en catch-all-rute.
Eksempel: Implementering af en 404-side
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
function NotFound() {
return (
404 - Ikke Fundet
Siden, du leder efter, eksisterer ikke.
Gå tilbage til forsiden
);
}
function App() {
return (
} />
} />
} />
);
}
I dette eksempel:
<Route path="*" element={<NotFound />} />
-ruten er en catch-all-rute, der matcher enhver URL, som ikke matcher nogen af de andre definerede ruter.- Det er vigtigt at placere denne rute sidst i
<Routes>
-komponenten, så den kun matcher, hvis ingen anden rute matcher.
6. Strategier for Dataindlæsning med React Router v6
React Router v6 inkluderer ikke indbyggede dataindlæsningsmekanismer som sin forgænger (React Router v5 med `useRouteMatch`). Den giver dog værktøjerne til at implementere forskellige dataindlæsningsstrategier effektivt.
Mulighed 1: Hentning af Data i Komponenter
Den enkleste tilgang er at hente data direkte inden i den komponent, der gengiver ruten. Du kan bruge useEffect
-hooket til at hente data, når komponenten monteres, eller når URL-parametrene ændres.
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 Indlæser...
;
if (error) return Fejl: {error.message}
;
if (!product) return Produkt ikke fundet
;
return (
{product.name}
{product.description}
);
}
export default ProductDetails;
Denne tilgang er ligetil, men kan føre til duplikering af kode, hvis du har brug for at hente data i flere komponenter. Den er også mindre effektiv, fordi dataindhentningen først starter, efter at komponenten er monteret.
Mulighed 2: Brug af en Custom Hook til Dataindhentning
For at reducere kodeduplikering kan du oprette en custom hook, der indkapsler logikken for dataindhentning. Denne hook kan derefter genbruges i flere komponenter.
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;
Derefter kan du bruge denne hook i dine komponenter:
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 Indlæser...
;
if (error) return Fejl: {error.message}
;
if (!product) return Produkt ikke fundet
;
return (
{product.name}
{product.description}
);
}
export default ProductDetails;
Mulighed 3: Brug af et Routing-bibliotek med Dataindhentningskapaciteter (TanStack Router, Remix)
Biblioteker som TanStack Router og Remix tilbyder indbyggede dataindhentningsmekanismer, der integreres problemfrit med routing. Disse biblioteker tilbyder ofte funktioner som:
- Loaders: Funktioner, der udføres *før* en rute gengives, hvilket giver dig mulighed for at hente data og videregive det til komponenten.
- Actions: Funktioner, der håndterer formularindsendelser og datamutationer.
Brug af et sådant bibliotek kan drastisk forenkle dataindlæsning og forbedre ydeevnen, især for komplekse applikationer.
Server Side Rendering (SSR) og Static Site Generation (SSG)
For forbedret SEO og indledende indlæsningsydelse, overvej at bruge SSR eller SSG med frameworks som Next.js eller Gatsby. Disse frameworks giver dig mulighed for at hente data på serveren eller under byggetid og servere præ-renderet HTML til klienten. Dette eliminerer behovet for, at klienten skal hente data ved den indledende indlæsning, hvilket resulterer i en hurtigere og mere SEO-venlig oplevelse.
7. Arbejde med Forskellige Router-typer
React Router v6 tilbyder forskellige router-implementeringer, der passer til forskellige miljøer og anvendelsestilfælde:
- BrowserRouter: Bruger HTML5 history API (
pushState
,replaceState
) til navigation. Det er det mest almindelige valg for webapplikationer, der kører i et browsermiljø. - HashRouter: Bruger hash-delen af URL'en (
#
) til navigation. Dette er nyttigt for applikationer, der skal understøtte ældre browsere, eller som er implementeret på servere, der ikke understøtter HTML5 history API. - MemoryRouter: Holder historikken for din "URL" i hukommelsen (et array af URL'er). Nyttigt i miljøer som React Native og til test.
Vælg den router-type, der bedst passer til din applikations krav og miljø.
Konklusion
React Router v6 tilbyder en omfattende og fleksibel routing-løsning til React-applikationer. Ved at forstå og anvende de navigationsmønstre, der er diskuteret i denne blogpost, kan du bygge robuste, brugervenlige og vedligeholdelsesvenlige webapplikationer. Fra deklarativ routing med <Routes>
og <Route>
til dynamiske ruter med URL-parametre, programmatisk navigation med useNavigate
og effektive dataindlæsningsstrategier, giver React Router v6 dig mulighed for at skabe problemfri navigationsoplevelser for dine brugere. Overvej at udforske avancerede routing-biblioteker og SSR/SSG-frameworks for endnu større kontrol og ydeevneoptimering. Husk at tilpasse disse mønstre til dine specifikke applikationskrav og altid prioritere en klar og intuitiv brugeroplevelse.