Jak zacząć korzystać z routingu w aplikacjach React

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. Sprawdź jak zacząć korzystać z React Router

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.

npm developer

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ń: PUSHPOP 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:

react router tutorial

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.

path string

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

react application

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:

react router - create nested routes

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”:

react router - create nested routes

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:

how yo build dynamic routes with react router

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:

how yo build dynamic routes with react router

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:

react router - path parameters - search params

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:

  1. Scaffold the project
  2. Setting up React Router
  3. Cleanin’ Out My Closet
  4. It’s not time for styling
  5. Add Router component
  6. Add navigation and links
  7. Add the first route
  8. Add first nested routes and Outlet
  9. Add index routes
  10. Use URL Params
  11. Use search params
  12. 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.

Udostępnij post:

Możesz także polubić

Kariera w branży technologicznej: Jak rozwijać swoje umiejętności

Jesteś programistą i chciałbyś się rozwijać? W internecie znajdziesz pełno materiałów o tym, jak to zrobić. Pomimo tego nie uciekaj — mam coś, co Cię zaciekawi. Czy wiesz, że Adam Małysz — legendarny polski skoczek, zanim został mistrzem latania, to był dekarzem? Nie śmiem się porównywać z Panem Adamem, natomiast są dwie rzeczy, które nas łączą.

Ja też byłem dekarzem i też udało mi się przebranżowić. Może nie w tak spektakularny sposób, ale jednak. W tym artykule podzielę się z Tobą moim osobistym doświadczeniem, które zdobyłem na drodze od dekarza przez programistę do tech leada i dam Ci wskazówki, które będziesz mógł zastosować, aby się rozwijać i awansować, a może nawet zmienić diametralnie swoją karierę.

Czytaj więcej
AHA stack przywróćmy prostotę frontendu

AHA! Przywróćmy prostotę Frontendu

Czy zastanawiałeś się, dlaczego w dzisiejszych czasach, gdy mamy dostęp do najnowszych technologii i rozwiązań, projekty IT nadal kończą się fiaskiem? Czy nie uważasz, że w wielu przypadkach zamiast upraszczać to komplikujemy sobie życie i pracę? Czasami mniej znaczy więcej, zwłaszcza w świecie frontendu! Czytaj dalej i dowiedz się czym jest AHA stack i jak robić frontend prościej.

Czytaj więcej