Kurs JavaScript i React · Moduł 6: React Router

Parametry URL w kosmicznej nawigacji

11 min czytania
W tej lekcji10

W międzyplanetarnych podróżach, koordynaty i identyfikatory ciał niebieskich są kluczowe dla nawigacji. Podobnie w React Router, parametry URL pozwalają na precyzyjne kierowanie użytkownika do konkretnych zasobów aplikacji. W tym module poznamy, jak używać, odczytywać i manipulować parametrami URL w naszych kosmicznych aplikacjach.

Czym są parametry URL?

Parametry URL to zmienne części adresu URL, które mogą zawierać dynamiczne wartości. W React Router występują w dwóch głównych formach:

  1. Parametry ścieżki (path parameters) - wbudowane w strukturę URL (np. /planets/:planetId)
  2. Parametry zapytania (query parameters) - dodawane po znaku zapytania (np. /planets?type=rocky&inhabited=true)

Parametry ścieżki (Path Parameters)

Parametry ścieżki są częścią samej struktury URL i definiowane są przez dwukropek (:) w definicji trasy.

Definiowanie tras z parametrami ścieżki

1import { Routes, Route } from 'react-router-dom';
2
3function AppRoutes() {
4  return (
5    <Routes>
6      <Route path="/" element={<Dashboard />} />
7      <Route path="/planets/:planetId" element={<PlanetDetails />} />
8      <Route path="/missions/:year/:missionId" element={<MissionDetails />} />
9    </Routes>
10  );
11}

W powyższym przykładzie:

  • :planetId to parametr w ścieżce /planets/:planetId
  • :year i :missionId to parametry w ścieżce /missions/:year/:missionId

Te ścieżki będą pasować do URL-i takich jak:

  • /planets/mars
  • /planets/jupiter
  • /missions/2150/mars-expedition

Dostęp do parametrów ścieżki za pomocą useParams

Do odczytania wartości parametrów ścieżki w komponencie używamy hooka useParams:

1import { useParams } from 'react-router-dom';
2
3function PlanetDetails() {
4  const { planetId } = useParams();
5
6  return (
7    <div className="planet-details">
8      <h1>Szczegóły planety: {planetId}</h1>
9      {/* Reszta komponentu używająca wartości planetId */}
10    </div>
11  );
12}

W bardziej złożonym komponencie możemy użyć parametru do pobrania danych:

1import { useParams } from 'react-router-dom';
2import { useState, useEffect } from 'react';
3
4function PlanetDetails() {
5  const { planetId } = useParams();
6  const [planetData, setPlanetData] = useState(null);
7  const [loading, setLoading] = useState(true);
8  const [error, setError] = useState(null);
9
10  useEffect(() => {
11    // Resetujemy stan przy zmianie parametru
12    setLoading(true);
13    setError(null);
14
15    // Pobieramy dane dla konkretnej planety
16    fetch(`https://api.space-explorer.com/planets/${planetId}`)
17      .then(response => {
18        if (!response.ok) {
19          throw new Error('Nie można pobrać danych planety');
20        }
21        return response.json();
22      })
23      .then(data => {
24        setPlanetData(data);
25        setLoading(false);
26      })
27      .catch(err => {
28        setError(err.message);
29        setLoading(false);
30      });
31  }, [planetId]); // Ponowne wykonanie efektu przy zmianie planetId
32
33  if (loading) return <div>Ładowanie danych planety...</div>;
34  if (error) return <div>Błąd: {error}</div>;
35  if (!planetData) return <div>Nie znaleziono planety</div>;
36
37  return (
38    <div className="planet-details">
39      <h1>{planetData.name}</h1>
40      <div className="planet-info">
41        <p>Średnica: {planetData.diameter} km</p>
42        <p>Odległość od Słońca: {planetData.distanceFromSun} mln km</p>
43        <p>Temperatura powierzchni: {planetData.surfaceTemperature}°C</p>
44        <p>Typ: {planetData.type}</p>
45      </div>
46      {/* Więcej informacji o planecie */}
47    </div>
48  );
49}

Opcjonalne parametry ścieżki

Dziennik misji ma dwa widoki: listę wszystkich misji pod adresem /missions i misje z jednego roku, np. /missions/2150. Rok raz jest w adresie, a raz go nie ma. Od wersji 6.5 (grudzień 2022, tak samo w v7 i v8) React Router pozwala oznaczyć taki segment jako opcjonalny: wystarczy dopisać znak zapytania na jego końcu.

1<Routes>
2  <Route path="/missions/:year?" element={<MissionsList />} />
3</Routes>

Jedna trasa obsługuje teraz oba adresy: /missions i /missions/2150. Znak zapytania dotyczy tylko segmentu, przy którym stoi, dlatego adres /missions/2150/06 do tej trasy nie pasuje. Tak samo działa zapis /missions/:year?/:month? z lekcji o konfiguracji routingu: każdy z dwóch segmentów jest opcjonalny osobno.

Parametr odczytujesz tak jak wcześniej, hookiem useParams. Nowe jest tylko to, że przy adresie bez roku year ma wartość undefined, więc komponent musi obsłużyć oba przypadki:

1import { useParams } from 'react-router-dom';
2
3function MissionsList() {
4  const { year } = useParams();
5
6  return <h2>{year ? `Misje z roku ${year}` : 'Wszystkie misje'}</h2>;
7}

Komponent nie wie, pod którym adresem go wyrenderowano, i nie musi tego wiedzieć. Dostaje year albo undefined i na tej podstawie wybiera nagłówek. Opcjonalny może być też segment statyczny, czyli zwykłe słowo w ścieżce zamiast parametru:

1<Route path="/crew/:memberId/edit?" element={<CrewMember />} />

Ta trasa pasuje zarówno do /crew/ra, jak i do /crew/ra/edit, i w obu przypadkach renderuje ten sam komponent CrewMember.

W wersjach od 6.0 do 6.4 znak zapytania nie działał, więc trzeba było zdefiniować dwie osobne trasy z tym samym elementem. Ten zapis jest nadal poprawny i spotkasz go w starszych projektach:

1<Routes>
2  <Route path="/missions" element={<MissionsList />} />
3  <Route path="/missions/:year" element={<MissionsList />} />
4</Routes>

Trzecia droga to parametry zapytania, które z natury są opcjonalne. Polecam prostą zasadę: segment opcjonalny wybieraj, gdy wartość buduje hierarchię adresu, jak rok w dzienniku misji, a parametry zapytania, gdy to filtry, które można dowolnie łączyć. Parametry zapytania poznasz w następnej sekcji.

Parametry zapytania (Query Parameters)

Parametry zapytania to pary klucz-wartość dodawane po znaku zapytania (?) w URL. Przykład: /search?query=mars&category=planets

Dostęp do parametrów zapytania za pomocą useSearchParams

Hook useSearchParams pozwala na odczytanie i manipulację parametrami zapytania:

1import { useSearchParams } from 'react-router-dom';
2
3function PlanetSearch() {
4  // searchParams to obiekt URLSearchParams
5  // setSearchParams to funkcja do aktualizacji parametrów
6  const [searchParams, setSearchParams] = useSearchParams();
7
8  // Odczytanie wartości parametrów
9  const query = searchParams.get('query') || '';
10  const type = searchParams.get('type') || 'all';
11
12  // Funkcja obsługująca wyszukiwanie
13  const handleSearch = (e) => {
14    e.preventDefault();
15    const formData = new FormData(e.target);
16    const newQuery = formData.get('searchQuery');
17    const newType = formData.get('planetType');
18
19    // Aktualizacja parametrów zapytania
20    setSearchParams({ query: newQuery, type: newType });
21  };
22
23  return (
24    <div className="planet-search">
25      <h1>Wyszukiwarka planet</h1>
26
27      <form onSubmit={handleSearch}>
28        <input
29          name="searchQuery"
30          defaultValue={query}
31          placeholder="Wpisz nazwę planety..."
32        />
33
34        <select name="planetType" defaultValue={type}>
35          <option value="all">Wszystkie typy</option>
36          <option value="rocky">Skaliste</option>
37          <option value="gas-giant">Gazowe olbrzymy</option>
38          <option value="ice-giant">Lodowe olbrzymy</option>
39        </select>
40
41        <button type="submit">Szukaj</button>
42      </form>
43
44      <div className="search-results">
45        {/* Wyniki wyszukiwania w zależności od query i type */}
46        <p>Szukana fraza: {query || '(brak)'}</p>
47        <p>Typ planety: {type}</p>
48      </div>
49    </div>
50  );
51}

Manipulowanie parametrami zapytania

Możemy manipulować parametrami zapytania w różny sposób:

1// Ustawienie nowych parametrów (zastępuje wszystkie istniejące)
2setSearchParams({ query: 'mars', type: 'rocky' });
3
4// Dodanie lub aktualizacja parametru bez usuwania istniejących
5setSearchParams(params => {
6  params.set('query', 'mars');
7  return params;
8});
9
10// Usunięcie parametru
11setSearchParams(params => {
12  params.delete('type');
13  return params;
14});
15
16// Sprawdzenie, czy parametr istnieje
17const hasType = searchParams.has('type');
18
19// Pobranie wszystkich wartości dla parametru (jeśli występuje wielokrotnie)
20const allCategories = searchParams.getAll('category');

Parametry zapytania vs. parametry ścieżki - kiedy używać których?

Parametry ścieżki:

  • Do identyfikacji głównego zasobu (np. /planets/mars)
  • Gdy parametr jest obowiązkowy
  • Gdy struktura URL powinna odzwierciedlać hierarchię zasobów
  • Przykłady: ID planety, rok misji, nazwa gwiazdozbioru

Parametry zapytania:

  • Do filtrowania, sortowania, paginacji
  • Dla parametrów opcjonalnych
  • Gdy mamy wiele kombinacji parametrów
  • Przykłady: kryteria wyszukiwania, strona wyników, limity, filtry

Łączenie parametrów ścieżki i zapytania

Możemy łączyć oba rodzaje parametrów dla większej elastyczności:

1// URL: /planets/mars?tab=geology&unit=metric
2
3import { useParams, useSearchParams } from 'react-router-dom';
4
5function PlanetDetails() {
6  const { planetId } = useParams();
7  const [searchParams] = useSearchParams();
8
9  const activeTab = searchParams.get('tab') || 'overview';
10  const unit = searchParams.get('unit') || 'metric';
11
12  return (
13    <div>
14      <h1>Planeta: {planetId}</h1>
15
16      <div className="tabs">
17        <TabLink to={`/planets/${planetId}?tab=overview&unit=${unit}`}
18          active={activeTab === 'overview'}>
19          Przegląd
20        </TabLink>
21        <TabLink to={`/planets/${planetId}?tab=geology&unit=${unit}`}
22          active={activeTab === 'geology'}>
23          Geologia
24        </TabLink>
25        <TabLink to={`/planets/${planetId}?tab=atmosphere&unit=${unit}`}
26          active={activeTab === 'atmosphere'}>
27          Atmosfera
28        </TabLink>
29      </div>
30
31      <div className="unit-switcher">
32        <UnitToggle
33          metric={unit === 'metric'}
34          onChange={(isMetric) => {
35            const newUnit = isMetric ? 'metric' : 'imperial';
36            // Aktualizacja tylko parametru unit, zachowanie tab
37            searchParams.set('unit', newUnit);
38            setSearchParams(searchParams);
39          }}
40        />
41      </div>
42
43      {/* Zawartość zależna od activeTab i unit */}
44    </div>
45  );
46}

createSearchParams - ułatwienie tworzenia parametrów zapytania

Funkcja createSearchParams pomaga w tworzeniu parametrów zapytania z obiektów JavaScript:

1import { createSearchParams, useNavigate } from 'react-router-dom';
2
3function PlanetFilterPanel() {
4  const navigate = useNavigate();
5
6  const applyFilters = (filters) => {
7    // Konwersja obiektu filtrów na parametry URL
8    const params = createSearchParams({
9      type: filters.type,
10      minSize: filters.minSize,
11      hasWater: filters.hasWater ? 'true' : undefined,
12      sortBy: filters.sortBy
13    });
14
15    // Nawigacja z parametrami
16    navigate({
17      pathname: '/planets',
18      search: `?${params}`
19    });
20  };
21
22  return (
23    <form onSubmit={(e) => {
24      e.preventDefault();
25      const form = e.target;
26      applyFilters({
27        type: form.type.value,
28        minSize: form.minSize.value,
29        hasWater: form.hasWater.checked,
30        sortBy: form.sortBy.value
31      });
32    }}>
33      {/* Formularz filtrowania */}
34      <button type="submit">Zastosuj filtry</button>
35    </form>
36  );
37}

Generowanie linków z parametrami

Tworząc linki z parametrami, możemy używać:

Dla parametrów ścieżki:

1// Proste łączenie ciągów
2<Link to={`/planets/${planetId}`}>
3  Szczegóły planety {planetName}
4</Link>
5
6// Użycie obiektu (bardziej elastyczne)
7<Link to={{
8  pathname: `/planets/${planetId}`,
9}}>
10  Szczegóły planety {planetName}
11</Link>

Dla parametrów zapytania:

1import { Link, createSearchParams } from 'react-router-dom';
2
3// Z użyciem createSearchParams
4<Link to={{
5  pathname: '/planets',
6  search: `?${createSearchParams({
7    type: 'rocky',
8    inhabited: 'true'
9  })}`
10}}>
11  Zamieszkane planety skaliste
12</Link>
13
14// Lub ręczne tworzenie parametrów
15<Link to={`/planets?type=rocky&inhabited=true`}>
16  Zamieszkane planety skaliste
17</Link>

Pełny przykład aplikacji z parametrami URL

Zobaczmy teraz kompletny przykład kosmicznej aplikacji wykorzystującej zarówno parametry ścieżki, jak i parametry zapytania:

1import React, { useState, useEffect } from 'react';
2import {
3  BrowserRouter,
4  Routes,
5  Route,
6  Link,
7  useParams,
8  useSearchParams,
9  createSearchParams,
10  useNavigate
11} from 'react-router-dom';
12
13// Symulacja API
14const planetsData = [
15  { id: 'mercury', name: 'Merkury', type: 'rocky', diameter: 4879, hasWater: false },
16  { id: 'venus', name: 'Wenus', type: 'rocky', diameter: 12104, hasWater: false },
17  { id: 'earth', name: 'Ziemia', type: 'rocky', diameter: 12742, hasWater: true },
18  { id: 'mars', name: 'Mars', type: 'rocky', diameter: 6779, hasWater: true },
19  { id: 'jupiter', name: 'Jowisz', type: 'gas-giant', diameter: 139820, hasWater: true },
20  { id: 'saturn', name: 'Saturn', type: 'gas-giant', diameter: 116460, hasWater: true },
21  { id: 'uranus', name: 'Uran', type: 'ice-giant', diameter: 50724, hasWater: true },
22  { id: 'neptune', name: 'Neptun', type: 'ice-giant', diameter: 49244, hasWater: true },
23];
24
25// Komponenty główne
26function PlanetsList() {
27  const [searchParams, setSearchParams] = useSearchParams();
28  const navigate = useNavigate();
29
30  // Odczytanie parametrów zapytania
31  const type = searchParams.get('type') || 'all';
32  const hasWater = searchParams.get('hasWater');
33  const sortBy = searchParams.get('sortBy') || 'name';
34
35  // Filtrowanie planet
36  const filteredPlanets = planetsData
37    .filter(planet => type === 'all' || planet.type === type)
38    .filter(planet => hasWater === null || (hasWater === 'true' && planet.hasWater))
39    .sort((a, b) => {
40      if (sortBy === 'name') return a.name.localeCompare(b.name);
41      if (sortBy === 'diameter') return b.diameter - a.diameter;
42      return 0;
43    });
44
45  // Funkcja aktualizująca filtry
46  const updateFilters = (newFilters) => {
47    const params = createSearchParams({
48      ...Object.fromEntries(searchParams),
49      ...newFilters
50    });
51    setSearchParams(params);
52  };
53
54  return (
55    <div className="planets-list">
56      <h1>Katalog planet</h1>
57
58      <div className="filters">
59        <label>
60          Typ planety:
61          <select
62            value={type}
63            onChange={(e) => updateFilters({ type: e.target.value })}
64          >
65            <option value="all">Wszystkie</option>
66            <option value="rocky">Skaliste</option>
67            <option value="gas-giant">Gazowe olbrzymy</option>
68            <option value="ice-giant">Lodowe olbrzymy</option>
69          </select>
70        </label>
71
72        <label>
73          <input
74            type="checkbox"
75            checked={hasWater === 'true'}
76            onChange={(e) => updateFilters({ hasWater: e.target.checked ? 'true' : null })}
77          />
78          Tylko z wodą
79        </label>
80
81        <label>
82          Sortuj wg:
83          <select
84            value={sortBy}
85            onChange={(e) => updateFilters({ sortBy: e.target.value })}
86          >
87            <option value="name">Nazwa</option>
88            <option value="diameter">Rozmiar</option>
89          </select>
90        </label>
91      </div>
92
93      <ul className="planets-grid">
94        {filteredPlanets.map(planet => (
95          <li key={planet.id} className={`planet ${planet.type}`}>
96            <Link to={`/planets/${planet.id}`}>
97              <h2>{planet.name}</h2>
98              <p>Typ: {planet.type}</p>
99              <p>Średnica: {planet.diameter} km</p>
100              <p>Woda: {planet.hasWater ? 'Obecna' : 'Brak'}</p>
101            </Link>
102          </li>
103        ))}
104      </ul>
105
106      {filteredPlanets.length === 0 && (
107        <p>Nie znaleziono planet spełniających kryteria.</p>
108      )}
109
110      <button onClick={() => navigate('/')}>
111        Powrót do centrum kontroli
112      </button>
113    </div>
114  );
115}
116
117function PlanetDetails() {
118  const { planetId } = useParams();
119  const [searchParams, setSearchParams] = useSearchParams();
120  const navigate = useNavigate();
121
122  // Odczytanie parametrów zapytania
123  const activeTab = searchParams.get('tab') || 'overview';
124
125  // Znalezienie planety o danym ID
126  const planet = planetsData.find(p => p.id === planetId);
127
128  // Jeśli nie znaleziono planety
129  if (!planet) {
130    return (
131      <div className="planet-not-found">
132        <h1>Planeta nie istnieje!</h1>
133        <p>Nie znaleziono planety o identyfikatorze: {planetId}</p>
134        <button onClick={() => navigate('/planets')}>
135          Powrót do katalogu planet
136        </button>
137      </div>
138    );
139  }
140
141  // Zmiana aktywnej zakładki
142  const changeTab = (tab) => {
143    setSearchParams({ tab });
144  };
145
146  return (
147    <div className="planet-details">
148      <h1>{planet.name}</h1>
149
150      <div className="tabs">
151        <button
152          className={activeTab === 'overview' ? 'active' : ''}
153          onClick={() => changeTab('overview')}
154        >
155          Przegląd
156        </button>
157        <button
158          className={activeTab === 'composition' ? 'active' : ''}
159          onClick={() => changeTab('composition')}
160        >
161          Skład
162        </button>
163        <button
164          className={activeTab === 'exploration' ? 'active' : ''}
165          onClick={() => changeTab('exploration')}
166        >
167          Eksploracja
168        </button>
169      </div>
170
171      <div className="tab-content">
172        {activeTab === 'overview' && (
173          <div>
174            <h2>Przegląd planety {planet.name}</h2>
175            <p>Typ: {planet.type}</p>
176            <p>Średnica: {planet.diameter} km</p>
177            <p>Woda: {planet.hasWater ? 'Obecna' : 'Brak'}</p>
178          </div>
179        )}
180
181        {activeTab === 'composition' && (
182          <div>
183            <h2>Skład planety {planet.name}</h2>
184            <p>Tu będą informacje o składzie planety...</p>
185          </div>
186        )}
187
188        {activeTab === 'exploration' && (
189          <div>
190            <h2>Eksploracja planety {planet.name}</h2>
191            <p>Tu będą informacje o misjach eksploracyjnych...</p>
192          </div>
193        )}
194      </div>
195
196      <Link to="/planets">Powrót do katalogu planet</Link>
197    </div>
198  );
199}
200
201function App() {
202  return (
203    <BrowserRouter>
204      <div className="space-app">
205        <header>
206          <h1>Kosmiczny System Nawigacyjny</h1>
207        </header>
208
209        <main>
210          <Routes>
211            <Route path="/" element={<Dashboard />} />
212            <Route path="/planets" element={<PlanetsList />} />
213            <Route path="/planets/:planetId" element={<PlanetDetails />} />
214            <Route path="*" element={<NotFound />} />
215          </Routes>
216        </main>
217
218        <footer>
219          <p>&copy; 2150 Międzyplanetarna Agencja Kosmiczna</p>
220        </footer>
221      </div>
222    </BrowserRouter>
223  );
224}
225
226// Pozostałe komponenty
227function Dashboard() {
228  return (
229    <div className="dashboard">
230      <h1>Centrum Kontroli Misji</h1>
231      <p>Witaj w systemie nawigacji kosmicznej!</p>
232      <Link to="/planets">Przeglądaj katalog planet</Link>
233    </div>
234  );
235}
236
237function NotFound() {
238  return (
239    <div className="not-found">
240      <h1>Błąd nawigacji: 404</h1>
241      <p>Zagubiony w kosmosie! Ta strona nie istnieje.</p>
242      <Link to="/">Powrót do Centrum Kontroli</Link>
243    </div>
244  );
245}
246
247export default App;

Najlepsze praktyki dla parametrów URL

  1. Używaj czytelnych nazw parametrów - powinny opisywać, co reprezentują
  2. Wybieraj odpowiedni typ parametrów - parametry ścieżki dla głównych zasobów, parametry zapytania dla filtrów
  3. Obsługuj brakujące parametry - zawsze zapewniaj wartości domyślne
  4. Waliduj parametry - sprawdzaj, czy wartości są poprawne przed użyciem
  5. Zachowuj stan parametrów zapytania - aktualizuj tylko te parametry, które się zmieniają
  6. Używaj parametrów do przechowywania stanu UI - ułatwia to udostępnianie i zapisywanie stanu

Podsumowanie

Parametry URL są potężnym narzędziem w nawigacji kosmicznej (i React Router). Pozwalają na:

  • Identyfikację konkretnych zasobów (parametry ścieżki)
  • Filtrowanie i sortowanie danych (parametry zapytania)
  • Zapamiętywanie stanu interfejsu użytkownika
  • Tworzenie udostępnialnych i zakładkowalnych linków
  • Obsługę historii przeglądarki

Dzięki nim, użytkownicy mogą precyzyjnie nawigować do konkretnych lokalizacji w kosmicznej aplikacji, a ty jako programista możesz tworzyć interaktywne i przyjazne dla użytkownika interfejsy.

Kod do tej lekcji: App.jsx
1import React from 'react';
2import { BrowserRouter, Routes, Route, Link, useParams } from 'react-router-dom';
3
4// Lista planet
5const planets = [
6  { id: 'mars', name: 'Mars', emoji: '', distance: '225M km' },
7  { id: 'jupiter', name: 'Jowisz', emoji: '', distance: '628M km' },
8  { id: 'saturn', name: 'Saturn', emoji: '', distance: '1.2B km' },
9  { id: 'neptune', name: 'Neptun', emoji: '', distance: '4.3B km' },
10];
11
12// Strona główna z listą planet
13function PlanetList() {
14  return (
15    <div className="planet-list">
16      <h1>Katalog Planet</h1>
17      <div className="planets-grid">
18        {planets.map(planet => (
19          <Link
20            key={planet.id}
21            to={`/planet/${planet.id}`}
22            className="planet-card"
23          >
24            <div className="planet-emoji">{planet.emoji}</div>
25            <h3>{planet.name}</h3>
26            <p>{planet.distance}</p>
27          </Link>
28        ))}
29      </div>
30    </div>
31  );
32}
33
34// Szczegóły planety - używamy useParams
35function PlanetDetails() {
36  const { planetId } = useParams();
37  const planet = planets.find(p => p.id === planetId);
38
39  if (!planet) {
40    return (
41      <div className="not-found">
42        <h1>Planeta nie znaleziona</h1>
43        <p>Nie odnaleziono planety o ID: {planetId}</p>
44        <Link to="/" className="back-link">← Wróć do katalogu</Link>
45      </div>
46    );
47  }
48
49  return (
50    <div className="planet-details">
51      <Link to="/" className="back-link">← Wróć do katalogu</Link>
52      <div className="planet-hero">
53        <div className="planet-emoji-large">{planet.emoji}</div>
54        <h1>{planet.name}</h1>
55      </div>
56      <div className="planet-info">
57        <div className="info-item">
58          <span className="label">ID:</span>
59          <span className="value">{planet.id}</span>
60        </div>
61        <div className="info-item">
62          <span className="label">Odległość od Ziemi:</span>
63          <span className="value">{planet.distance}</span>
64        </div>
65        <div className="info-item">
66          <span className="label">Parametr URL:</span>
67          <span className="value code">:planetId = "{planetId}"</span>
68        </div>
69      </div>
70    </div>
71  );
72}
73
74function App() {
75  return (
76    <BrowserRouter>
77      <div className="app">
78        <Routes>
79          <Route path="/" element={<PlanetList />} />
80          <Route path="/planet/:planetId" element={<PlanetDetails />} />
81        </Routes>
82      </div>
83    </BrowserRouter>
84  );
85}
86
87export default App;

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. Jaka jest kluczowa różnica między komponentami Link a NavLink?

Zadania praktyczne w grze

  • Układanie w poziomie

    Ułóż elementy składni Route w React Router v6:

  • Edytor kodu

    Dynamiczne parametry URL

  • Układanie w pionie

    Uporządkuj hierarchię routingu w aplikacji kosmicznej:

Przydatne artykuły