React to popularna biblioteka do tworzenia aplikacji jednostronicowych (SPA), które mogą być renderowane po stronie klienta. W SPA użytkownik końcowy, który zna Multi Pages, oczekuje następujacej funkcji: Routing, a jest to procedura, która utrzymuje synchronizację adresu URL przeglądarki z treścią.
Korzystając z routingu deklaratywnego, możesz kontrolować informacje o ruchu w aplikacji za pomocą wyrażenia „trasa powinna wyglądać tak…” i umieszczać komponenty w dowolnym miejscu. W rzeczywistości jest to biblioteka innej firmy znana ze swojej prostoty.
Co to jest React Router?
Sam React koncentruje się na budowaniu interfejsów użytkownika i brakuje mu w pełni zintegrowanego rozwiązania routingu. React Router to najpopularniejsza biblioteka routingu w React. Pozwala definiować ścieżki w tym samym stylu deklaratywnym, co większość innych bibliotek. Router umożliwia Twojej aplikacji nawigację poprzez zmianę adresu URL przeglądarki lub historii przeglądania, pozostając jednocześnie zsynchronizowanym z innymi elementami.
Zrozumieć routing
Logika dopasowania do komponentu jest delegowana do biblioteki path-to-regexp. Dzięki temu zachowaniu określasz, który komponent powinien być wyświetlany dla określonej ścieżki adresu URL.
Oznacza to, że jeśli masz na przykład stronę „o mnie”, a ścieżka tej strony to „/about-me”, musisz przypisać komponent, który Reacts będzie renderował dla tej konkretnej ścieżki.
Co robi React Router DOM?
React Router DOM umożliwia implementację dynamicznego routingu w aplikacjach internetowych. React RouterDOM obsługuje routing oparty na komponentach zgodnie z wymaganiami aplikacji i strukturą. Z kolei tradycyjna architektura routingu zapewnia usługi routingu w konfiguracji poza aktualnie aktywną aplikacją. React Router to najlepsze rozwiązanie do tworzenia aplikacji React działających w przeglądarce. React router DOM to najszybszy sposób tworzenia routingu w React.
Poznaj React Router
Ten samouczek jest podzielony na wiele obszarów. Naszym pierwszym zadaniem jest stworzenie aplikacji React i zainstalowanie React Routera za pomocą npm. Póżniej przejdziemy do kilku podstawowych funkcji React Routera. W trakcie kursu omówione zostaną poszczególne koncepcje i systemy budowy tych tras.
Pełny kod projektu jest opublikowany w tym repozytorium GitHub. Ten samouczek przedstawia koncepcje korzystania z routingu React, podstawy React, hooki i testowanie.
Wymagania wstępne
Przetestowałem kod w węźle 14.17.3. Skonfigurowałem projekt za pomocą Create React App. Będziesz także potrzebować podstawowej znajomości JavaScript, HTML i CSS oraz React, aby zrozumieć, co się tutaj dzieje, ale jeśli chcesz nauczyć się React Router, znasz te rzeczy.
Utworzenie projektu
Jak wspomniałem wcześniej, na potrzeby tego samouczka będziesz potrzebować Node zainstalowanego na komputerze. Możesz użyć tych instrukcji aby skonfigurować projekt React za pomocą aplikacji Create React.
Git commit ze zmianami z tego kroku: Scaffold the project
Konfiguracja React Router
Teraz możesz zainstalować React Router za pomocą npm lub przędzy. Użyjmy npm
$ npm install react-router-dom@6
Git commit ze zmianami z tego kroku: Setting up React Router
Czyszczenie
Zanim przejdziemy głębiej, wyczyśćmy trochę kodu wygenerowanego dla nas przez CRA.
Zamień plik index.js na tę treść:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<App />,
document.getElementById('root')
);
Usuń te pliki: reportWebVitals.js, index.css, logo.svg, App.css i App.test.js – kto potrzebuje testów??? Ale poczekaj, później możemy dodać własne testy, nie martw się, po prostu cię trolluję.
Zastąp App.js tą treścią:
import React from "react";
export const App = () => {
return <>
<h1>Hello, hello, hello</h1>
</>
}
export default App;
Zmień tytuł i opis w pliku public/index.html i usuń niepotrzebne komentarze. Końcowy wynik powinien wyglądać tak:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="React router tutorial"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>React Router example</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
Git commit ze zmianami z tego kroku: Cleanin’ Out My Closet
To nie czas na stylowanie
Tak, więc użyjmy React Bootstrap, który zapewnia pewne komponenty i style, aby skupić się na pisaniu kodu React. To dobre posunięcie, prawda?
$ npm install react-bootstrap bootstrap@5.1.3
Importuj style bootstrap w pliku index.js. Po prostu dodaj tę linię po innych importach:
import 'bootstrap/dist/css/bootstrap.min.css';
OK, to wszystko było łatwe. Zróbmy coś mniej trywialnego niż importowanie rzeczy z npm.
Git commit ze zmianami z tego kroku: It’s not time for styling
Dodanie komponentu Router
Aby React Router działał w Twojej aplikacji, musisz dodać Router. Zasadniczo oznacza to, że musisz otoczyć swoją aplikację routerem najwyższego poziomu, który sprawi, że wszystkie inne komponenty i haki React Router będą działać. Router jest stanowy i tworzy historię z początkową lokalizacją oraz subskrybuje adres URL.
React Router może subskrybować zmiany adresów URL dzięki obiektowi History. Każda akcja użytkownika, która zmienia adres URL, jest przechowywana w stosie historii.
TIstnieją trzy rodzaje tych działań: PUSH, POP i REPLACE.
- PUSH – do stosu historii dodawany jest nowy wpis
- POP – dzieje się tak, gdy użytkownik klika przyciski Wstecz lub Dalej w przeglądarce
- REPLACE – jest podobna do PUSH, ale zastępuje bieżący wpis w stosie historii zamiast dodawać nowy
Lokalizacja to obiekt zbudowany na górze okna. obiekt lokalizacji. W tym obiekcie można znaleźć informacje o adresie URL i generalnie reprezentuje on miejsce, w którym w danym momencie znajduje się użytkownik.
Istnieją trzy rodzaje routerów w React-router-dom:
- BrowserRouter – zalecane do uruchamiania React Router w przeglądarce internetowej
- HashRouter – is used for apps where the URL should not be sent to a server for some reason. It’s not recommended to use the Hash router unless you absolutely have to.
- MemoryRouter – jest używany w przypadku aplikacji, w przypadku których z jakiegoś powodu adres URL nie powinien być wysyłany na serwer. Nie zaleca się używania routera Hash, chyba że jest to absolutnie konieczne.
OK, więc opakujmy naszą aplikację przez BrowserRouter.
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from "react-router-dom";
import App from './App';
import 'bootstrap/dist/css/bootstrap.min.css';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
Git commit ze zmianami z tego kroku: Add Router component
Dodanie nawigacji i linków
Zaktualizuj plik komponentu aplikacji (App.js) o następującą zawartość:
import React from "react";
import { NavLink } from "react-router-dom";
import { Navbar, Container, Nav } from 'react-bootstrap'
export const App = () => {
return <>
<Navbar bg="light" expand="lg">
<Container>
<Navbar.Brand>
<NavLink to="/" style={{textDecoration: 'none', color: 'inherit'}}>Your account</NavLink>
</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<NavLink to="/address" className="nav-link">Address book</NavLink>
<NavLink to="/orders" className="nav-link">Orders</NavLink>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
<Container className="mt-3">
<h1>Hello, hello, hello</h1>
</Container>
</>
}
export default App;
Zaimportowaliśmy tutaj komponent NavLink z react-router-dom:
import { NavLink } from "react-router-dom";
Komponent NavLink jest specjalnym typem komponentu Link z dodatkową funkcją. Może mieć klasę „aktywną”, w której adres URL jest taki sam jak „do właściwości”.
Komponent Link React renderuje tag <a> z właściwością real href. Różnica w stosunku do prawdziwego tagu polega na tym, że React Router będzie obsługiwał nawigację do określonych lokalizacji, gdy użyjesz Link (i NavLink).
Tak więc w naszej aplikacji, nawet jeśli nie zadeklarowaliśmy jeszcze żadnych tras, adres URL jest zmieniany bez przeładowywania strony dzięki React Router.
Poza tym zaimportowaliśmy tam trochę Bootstrapa:
import { Navbar, Container, Nav } from 'react-bootstrap'
Strona powinna wyglądać tak:
Podsumowując, dodaliśmy trzy linki: Strona główna: /, Książka adresowa: /address i Zamówienia: /orders.
Git commit ze zmianami z tego kroku: Add navigation and links
Dodanie pierwszego route
React Router to deklaratywny framework routingu, co oznacza, że konfigurujesz trasy tak, aby korzystały ze standardowych komponentów React.
Pod koniec tego kroku masz teraz aplikację reagującą, która znajduje łącza nawigacyjne pokazujące komponenty dla każdej trasy.
Zaimplementujmy pierwszą trasę. Aby to zrobić, musimy po prostu zaimportować komponenty Route i Routes w aplikacji i użyć ich w następujący sposób:
import { Routes, BrowserRouter, Route} from "react-router-dom";
(...)
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
</Routes>
</BrowserRouter>
Mamy więc trasę, która obsługuje ścieżkę „/” i renderuje aplikację, komponent React. W zasadzie nic się do tej pory nie zmieniło w naszej aplikacji. Wdrażajmy inne trasy.
Git commit ze zmianami z tego kroku: Add the first route
Dodanie pierwszej zagnieżdzonej ścieżki
React Router wykorzystuje zagnieżdżone trasy, aby zapewnić najbardziej szczegółowe szczegóły routingu wewnątrz komponentów potomnych. Te trasy grupują informacje o trasach bezpośrednio w komponenty, aby renderować inne komponenty.
Pod koniec tego kroku będziesz mieć różne sposoby dostarczania informacji. To trochę dodatkowy kod, ale trasy utrzymują rodziców dziecka w ryzach. Nie każdy projekt używa zagnieżdżonej trasy: niektórzy wolą jawną listę.
Trasy zagnieżdżone pozwalają na zbudowanie złożonego systemu trasowania. Każda trasa definiuje część adresu URL poprzez segmenty, a jeden adres URL może pasować do wielu tras. Spójrz:
Oto nasza główna trasa:
/
Oto trasa do książki adresowej:
/address
A oto trasa po dane adresowe
/address/:addressId
Więc ścieżka jest zbutowana z trzech członów: / + address/ + :/addressId
Zaimplementujmy to. Zamień <Route path=”/” element={<App />} /> na:
<Route path="/" element={<App />} >
<Route path="address" element={<AddressBook />}>
<Route path=":addressId" element={<AddressDetails />} />
</Route>
</Route>
Oczywiście musimy zdefiniować dwa nowe związki: Książka adresowa i Szczegóły adresu
src/routes/AddressBook/addressBook.js:
import React from 'react'
export const addressBook = () => {
return <p>Address book will be here</p>
}
export default addressBook;
src/routes/AddressBook/index.js
export { default } from './addressBook';
Zrób to samo dla danych adresowych (i nie zapomnij zaimportować tych tras w index.js!)
To powinno zadziałać, ale poczekaj. Jeśli przejdziesz teraz do strony adresowej, zobaczysz, że trasa adresowa jest renderowana, ale wygląda prawie tak samo jak trasa indeksowa, ale z tą różnicą, że będzie tam akapit: Książka adresowa będzie tutaj.
Aby wyrenderować zawartość dowolnego elementu podrzędnego, musisz użyć komponentu Outlet, który renderuje następne dopasowanie w zestawie dopasowań.
Zaimportuj komponent Outlet React do komponentu aplikacji:
import { NavLink, Outlet } from "react-router-dom";
i dodaj to poniżej tagu <h1>
<Container className="mt-3">
<h1>Hello, hello, hello</h1>
<Outlet/>
</Container>
Teraz akapit z komponentu książki adresowej jest na swoim miejscu
Git commit ze zmianami z tego kroku: Add first nested routes and Outlet
Dodanie Index routes
Przejdźmy dalej i dodajmy trochę treści do książki adresowej. Najpierw dodaj kilka adresów:
const addresses = [
{
id: 1,
addressName: 'Polna 1, Wrocław'
},
{
id: 2,
addressName: 'Wrocławska 2, Warszawa'
}
];
Następnie wyrenderuj nawigację z adresami:
const navLinks = addresses.map(address => {
return <ListGroupItem key={address.id}>
<NavLink to={`/address/${address.id}`} key={address.id}>{address.addressName}</NavLink>
</ListGroupItem>
});
const shouldDisplayNav = navLinks && navLinks.length ? <ListGroup>{navLinks}</ListGroup> : <p>There are no addresses.</p>;
Zwróć wszystkie rzeczy z ładnym układem:
return addresses ? <Row>
<Col sm="3">
{shouldDisplayNav}
</Col>
<Col sm="9">
<Outlet/>
</Col>
</Row> : <Row>
<p>There are no addresses.</p>
</Row>
Nie zapomnij o imporcie:
import { NavLink, Outlet } from "react-router-dom";
import { ListGroupItem, ListGroup, Col, Row } from "react-bootstrap";
Strona powinna wyglądać tak:
Po prawej stronie nawigacji znajduje się miejsce na dane adresowe, ale początkowo jest to puste miejsce. Po kliknięciu adresu w nawigacji możesz zobaczyć szczegóły adresu.
Istnieje sposób na dodanie kilku ulepszeń! Dodajmy akapit o treści: „Proszę wybrać adres”. Aby to zrobić, możesz użyć innej całkiem fajnej funkcji React Router o nazwie: Indeksuj trasę
Dodaj ten kod do index.js do składnika trasy AddressBook:
<Route
index
element={
<p>Select an address.</p>
}
/>
Teraz, gdy przejdziesz do książki adresowej, domyślnie zobaczysz tekst „Select an address”:
Zróbmy coś podobnego dla trasy domowej:
<Route
index
element={
<>
<h2>Welcome in your account.</h2>
<p>Please use the navigation above to see Address book or your orders.</p>
</>
}
/>
Usuń ten kod z App.js
<h1>Hello, hello, hello</h1>
Strona główna wygląda teraz tak:
Git commit ze zmianami z tego kroku: Add index routes
Użycie URL params
Zdefiniowaliśmy już trasę dla szczegółów adresu, która otrzymuje parametr addressId:
<Route path=":addressId" element={<AddressDetails />} />
Po kliknięciu adresu URL zmienia się:
http://localhost:3000/address/1
http://localhost:3000/address/2
„1” i „2” w tym przypadku to adresy ID. Pytanie brzmi: jak obsłużymy te parametry w komponencie AddressDetails React?
useParams hook
React Router udostępnia hak useParams, który umożliwia obsługę parametrów adresu URL. Spójrz:
import React from 'react'
import { useParams } from "react-router-dom";
export const AddressDetails = () => {
const { addressId } = useParams();
return <p>Address details for {addressId} will be here</p>
}
export default AddressDetails;
Teraz adres addressId jest obsługiwany przez komponent AddressDetails:
Git commit ze zmianami z tego kroku: Use URL Params
Użycie search params
React Routes zapewnia hak useSearchParams, który umożliwia odczytanie i modyfikację części zapytania adresu URL (q=). Użyjmy go, aby dodać trochę filtrowania do aplikacji.
Najpierw zaimportuj hak useSearchParams w reklamie komponentu AddressBook React, pobierz searchParams i ustawSearchParams z niego:
import { useSearchParams } from "react-router-dom";
// below in the compoonent body:
const [searchParams, setSearchParams] = useSearchParams();
Po drugie, dodaj formularz wyszukiwania. Aby to zrobić, dodaj ten kod na początku funkcji zwracającej:
<Col sm="12">
<nav>
<InputGroup size="sm" className="mb-3">
<InputGroup.Text id="address-search">Search for an address</InputGroup.Text>
<FormControl aria-label="Search for an address"
aria-describedby="address-search"
value={searchParams.get("filter") || ""}
onChange={event => {
const filter = event.target.value;
if (filter) {
setSearchParams({ filter });
} else {
setSearchParams({});
}
}} />
</InputGroup>
</nav>
</Col>
Funkcja powiązana ze zdarzeniem onChange ustawia bieżącą wartość wejściową na parametr zapytania adresu URL.
Po trzecie, przeczytajmy parametr zapytania i filtrujmy według niego adresy:
const navLinks = addresses
.filter(address => {
const filter = searchParams.get('filter');
if (!filter) return true;
let name = address.addressName.toLowerCase();
return name.startsWith(filter.toLowerCase());
})
.map(address => {
return <ListGroupItem key={address.id}>
<NavLink to={`/address/${address.id}`} key={address.id}>{address.addressName}</NavLink>
</ListGroupItem>
});
W poprzednim kroku nazwaliśmy parametr według słowa: filter, a teraz możemy odczytać tę wartość, używając tego: searchParams.get(’filter’);
Zobacz filtrowanie w akcji:
Git commit ze zmianami z tego kroku: Use search params
Obsługa nieznalezionej ścieżki
Ostatnią rzeczą, którą chcę ci pokazać, jest trasa bez meczów. Jest to przypadek, gdy użytkownik przechodzi na trasę, która nie istnieje, na przykład/blablabla
Aby sobie z tym poradzić, dodaj następującą definicję komponentu trasy na końcu definicji komponentów trasy:
<Route
path="*"
element={
<main>
<p style={{padding: '30px', textAlign: 'center'}}>There's nothing here!</p>
</main>
}
/>
Ten kod obsługuje wszystkie routery, które nie są obsługiwane przez inne zdefiniowane komponenty tras. Z drugiej strony, jeśli żadne trasy nie pasują, te elementy zostaną wyrenderowane. Oczywiście możesz również użyć komponentu reagowania.
Git commit ze zmianami z tego kroku: Handle no matching route
Dodatkowa rzecz: protected Routes
Chroniona trasa służy do zapewnienia, że tylko zalogowani użytkownicy mogą korzystać z niektórych miejsc w Twojej witrynie. Zazwyczaj tworzymy komponent bezpiecznej trasy, aby ktoś w systemie mógł użyć /admin podczas próby połączenia. Jednak najpierw należy omówić niektóre aspekty React Router.
Zasadniczo możesz stworzyć specjalny komponent React, który sprawdzi, czy użytkownik może przejść do chronionej trasy, czy nie.
Działające Demo
Tutaj możesz zobaczyć demo aplikacji, którą stworzyliśmy za pomocą react-router:
react-router-tutorial-omega.vercel.app
Kod źródłowy
Tutaj możesz znaleźć kod źródłowy tego samouczka: https://github.com/Frodigo/react-router-tutorial
A tutaj commity dla każdego kroku:
- Scaffold the project
- Setting up React Router
- Cleanin’ Out My Closet
- It’s not time for styling
- Add Router component
- Add navigation and links
- Add the first route
- Add first nested routes and Outlet
- Add index routes
- Use URL Params
- Use search params
- Handle no matching route
Podsumowanie
React Router pozwala obsłużyć wszystkie trasy w aplikacji React. Możesz go użyć do aplikacji internetowej, a nawet do natywnej aplikacji React.
Router jest jednym z głównych komponentów React Router, a w przypadku aplikacji internetowych dostępny jest komponent React BrowserRouter, czyli implementacja routera korzystająca z interfejsu HTML5 History API.
React Router zapewnia inne niezbędne komponenty, takie jak Routes, Route, Link i NavLink.
Poza tym istnieje kilka haków, takich jak useParams, useSearchParams i useNavigate.
Tak więc pakiet react-router zawiera tylko komponenty i tylko haki, a to wszystko razem pozwala łatwo tworzyć złożone systemy routingu.