Polski

Odkryj kluczowe wzorce nawigacji w React Router v6. Poznaj deklaratywny routing, trasy dynamiczne, nawigację programową, zagnieżdżone trasy i strategie ładowania danych, aby tworzyć solidne i przyjazne dla użytkownika aplikacje internetowe.

React Router v6: Opanowanie Wzorców Nawigacji dla Nowoczesnych Aplikacji Webowych

React Router v6 to potężna i elastyczna biblioteka do routingu w aplikacjach React. Pozwala na tworzenie aplikacji jednostronicowych (SPA) z płynnym doświadczeniem użytkownika poprzez zarządzanie nawigacją bez pełnego przeładowywania strony. Ten wpis na blogu zagłębi się w podstawowe wzorce nawigacji z użyciem React Router v6, dostarczając wiedzy i przykładów do budowy solidnych i przyjaznych dla użytkownika aplikacji internetowych.

Zrozumienie Podstawowych Koncepcji React Router v6

Zanim przejdziemy do konkretnych wzorców, omówmy kilka fundamentalnych koncepcji:

1. Routing Deklaratywny z <Routes> i <Route>

Podstawą React Router v6 jest routing deklaratywny. Definiujesz swoje trasy za pomocą komponentów <Routes> i <Route>. Komponent <Routes> działa jako kontener dla tras, a komponent <Route> definiuje konkretną trasę i komponent do wyrenderowania, gdy ta trasa pasuje do bieżącego adresu URL.

Przykład: Podstawowa Konfiguracja Tras

Oto podstawowy przykład konfiguracji tras dla prostej aplikacji:


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;

W tym przykładzie definiujemy trzy trasy:

Komponent BrowserRouter umożliwia routing oparty na historii przeglądarki. React Router dopasowuje bieżący URL do zdefiniowanych tras i renderuje odpowiedni komponent.

2. Trasy Dynamiczne z Parametrami URL

Trasy dynamiczne pozwalają tworzyć trasy, które mogą obsługiwać różne wartości w adresie URL. Jest to przydatne do wyświetlania treści na podstawie unikalnego identyfikatora, takiego jak ID produktu czy ID użytkownika. React Router v6 używa symbolu : do definiowania parametrów URL.

Przykład: Wyświetlanie Szczegółów Produktu

Załóżmy, że masz aplikację e-commerce i chcesz wyświetlać szczegóły każdego produktu na podstawie jego ID. Możesz zdefiniować trasę dynamiczną w ten sposób:


import { BrowserRouter, Routes, Route, useParams } from "react-router-dom";

function ProductDetails() {
  const { productId } = useParams();

  // Pobierz szczegóły produktu na podstawie productId
  // ...

  return (
    

Szczegóły produktu

ID produktu: {productId}

{/* Wyświetl tutaj szczegóły produktu */}
); } function App() { return ( } /> ); } export default App;

W tym przykładzie:

Przykład Internacjonalizacji: Obsługa Kodów Językowych

Dla wielojęzycznej strony internetowej możesz użyć trasy dynamicznej do obsługi kodów językowych:


} />

Ta trasa pasowałaby do adresów URL takich jak /en/about, /pl/about i /de/about. Parametr lang może być następnie użyty do załadowania odpowiednich zasobów językowych.

3. Nawigacja Programowa z useNavigate

Chociaż routing deklaratywny jest świetny dla statycznych linków, często trzeba nawigować programowo w oparciu o działania użytkownika lub logikę aplikacji. React Router v6 dostarcza do tego celu hooka useNavigate. useNavigate zwraca funkcję, która pozwala na nawigację do różnych tras.

Przykład: Przekierowanie po Wysłaniu Formularza

Załóżmy, że masz formularz i chcesz przekierować użytkownika na stronę z podziękowaniem po pomyślnym przesłaniu formularza:


import { useNavigate } from "react-router-dom";

function MyForm() {
  const navigate = useNavigate();

  const handleSubmit = async (event) => {
    event.preventDefault();

    // Prześlij dane formularza
    // ...

    // Przekieruj na stronę sukcesu po pomyślnym przesłaniu
    navigate("/success");
  };

  return (
    
{/* Pola formularza */}
); } export default MyForm;

W tym przykładzie:

Przekazywanie Stanu Podczas Nawigacji

Możesz także przekazać stan wraz z nawigacją, używając drugiego argumentu funkcji navigate:


navigate("/confirmation", { state: { orderId: "12345" } });

Pozwala to na przekazanie danych do komponentu docelowego, do których można uzyskać dostęp za pomocą hooka useLocation.

4. Zagnieżdżone Trasy i Układy (Layouts)

Zagnieżdżone trasy pozwalają tworzyć hierarchiczne struktury routingu, gdzie jedna trasa jest zagnieżdżona w drugiej. Jest to przydatne do organizowania złożonych aplikacji z wieloma poziomami nawigacji. Pomaga to w tworzeniu układów, w których pewne elementy interfejsu użytkownika są stale obecne w całej sekcji aplikacji.

Przykład: Sekcja Profilu Użytkownika

Załóżmy, że masz sekcję profilu użytkownika z zagnieżdżonymi trasami do wyświetlania informacji o profilu, ustawień i zamówień:


import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

function Profile() {
  return (
    

Profil użytkownika

  • Informacje o profilu
  • Ustawienia
  • Zamówienia
} /> } /> } />
); } function ProfileInformation() { return

Komponent informacji o profilu

; } function Settings() { return

Komponent ustawień

; } function Orders() { return

Komponent zamówień

; } function App() { return ( } /> ); } export default App;

W tym przykładzie:

Znak * w trasie nadrzędnej jest kluczowy; oznacza on, że trasa nadrzędna powinna pasować do każdej podścieżki, co pozwala na prawidłowe dopasowanie zagnieżdżonych tras wewnątrz komponentu Profile.

5. Obsługa Błędów "Nie Znaleziono" (404)

Niezbędne jest obsłużenie przypadków, w których użytkownik przechodzi do trasy, która nie istnieje. React Router v6 ułatwia to dzięki trasie typu catch-all (łapiącej wszystko).

Przykład: Implementacja Strony 404


import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

function NotFound() {
  return (
    

404 - Nie znaleziono

Strona, której szukasz, nie istnieje.

Wróć na stronę główną
); } function App() { return ( } /> } /> } /> ); }

W tym przykładzie:

6. Strategie Ładowania Danych w React Router v6

React Router v6 nie zawiera wbudowanych mechanizmów ładowania danych, jak jego poprzednik (React Router v5 z `useRouteMatch`). Jednakże, dostarcza narzędzi do efektywnej implementacji różnych strategii ładowania danych.

Opcja 1: Pobieranie Danych w Komponentach

Najprostszym podejściem jest pobieranie danych bezpośrednio w komponencie, który renderuje trasę. Możesz użyć hooka useEffect do pobierania danych, gdy komponent jest montowany lub gdy zmieniają się parametry URL.


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(`Błąd HTTP! status: ${response.status}`);
        }
        const data = await response.json();
        setProduct(data);
        setLoading(false);
      } catch (e) {
        setError(e);
        setLoading(false);
      }
    }

    fetchProduct();
  }, [productId]);

  if (loading) return 

Ładowanie...

; if (error) return

Błąd: {error.message}

; if (!product) return

Nie znaleziono produktu

; return (

{product.name}

{product.description}

); } export default ProductDetails;

To podejście jest proste, ale może prowadzić do powielania kodu, jeśli musisz pobierać dane w wielu komponentach. Jest również mniej wydajne, ponieważ pobieranie danych rozpoczyna się dopiero po zamontowaniu komponentu.

Opcja 2: Użycie Niestandardowego Hooka do Pobierania Danych

Aby zredukować powielanie kodu, możesz stworzyć niestandardowy hook, który hermetyzuje logikę pobierania danych. Taki hook może być następnie ponownie użyty w wielu komponentach.


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(`Błąd HTTP! 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;

Następnie możesz użyć tego hooka w swoich komponentach:


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 

Ładowanie...

; if (error) return

Błąd: {error.message}

; if (!product) return

Nie znaleziono produktu

; return (

{product.name}

{product.description}

); } export default ProductDetails;

Opcja 3: Użycie Biblioteki do Routingu z Funkcjami Pobierania Danych (TanStack Router, Remix)

Biblioteki takie jak TanStack Router i Remix oferują wbudowane mechanizmy pobierania danych, które płynnie integrują się z routingiem. Te biblioteki często dostarczają funkcje takie jak:

Użycie takiej biblioteki może drastycznie uprościć ładowanie danych i poprawić wydajność, zwłaszcza w przypadku złożonych aplikacji.

Renderowanie po Stronie Serwera (SSR) i Generowanie Stron Statycznych (SSG)

Dla lepszego SEO i wydajności początkowego ładowania, rozważ użycie SSR lub SSG z frameworkami takimi jak Next.js czy Gatsby. Te frameworki pozwalają na pobieranie danych na serwerze lub podczas budowania aplikacji i serwowanie wstępnie wyrenderowanego HTML do klienta. Eliminuje to potrzebę pobierania danych przez klienta przy pierwszym ładowaniu, co skutkuje szybszym i bardziej przyjaznym dla SEO doświadczeniem.

7. Praca z Różnymi Typami Routerów

React Router v6 dostarcza różne implementacje routerów, aby dopasować się do różnych środowisk i przypadków użycia:

Wybierz typ routera, który najlepiej pasuje do wymagań i środowiska twojej aplikacji.

Podsumowanie

React Router v6 zapewnia kompleksowe i elastyczne rozwiązanie do routingu w aplikacjach React. Poprzez zrozumienie i stosowanie wzorców nawigacji omówionych w tym wpisie, możesz budować solidne, przyjazne dla użytkownika i łatwe w utrzymaniu aplikacje internetowe. Od routingu deklaratywnego z <Routes> i <Route>, przez trasy dynamiczne z parametrami URL, nawigację programową z useNavigate, po efektywne strategie ładowania danych, React Router v6 daje ci moc tworzenia płynnych doświadczeń nawigacyjnych dla twoich użytkowników. Rozważ zapoznanie się z zaawansowanymi bibliotekami do routingu oraz frameworkami SSR/SSG dla jeszcze większej kontroli i optymalizacji wydajności. Pamiętaj, aby dostosować te wzorce do specyficznych wymagań twojej aplikacji i zawsze stawiać na pierwszym miejscu jasne i intuicyjne doświadczenie użytkownika.