Frontend

Come usare React Router: le basi

Autore

Manuel Ricci

React Router è una libreria di routing per React che permette di gestire le navigazioni e il cambio di pagine in un'applicazione web o mobile in modo dinamico e reattivo. Con React Router, puoi creare un'interfaccia utente con pagine multiple senza ricaricare la pagina, migliorando l'esperienza utente e rendendo l'applicazione più simile a un'applicazione desktop.

Installazione

Prima di iniziare, assicurati di avere React e React DOM installati nel tuo progetto. Quindi, puoi installare React Router con npm o yarn:

1npm install react-router-dom
2# or
3yarn add react-router-dom

React Router 6.2 introduce nuovi modi per configurare e lavorare con il routing nell'applicazione React, tra cui l'uso di createBrowserRouter per creare un router. Questo approccio semplifica la configurazione delle route e migliora l'integrazione con funzionalità di caricamento lazy dei componenti e gestione degli errori.

Esempio pratico

Partiamo quindi con la creazione dei vari componenti necessari.

Un semplice header

1import React from 'react';
2import { Link } from 'react-router-dom';
3
4const Header: React.FC = () => {
5  return (
6    <header>
7      <nav>
8        <Link to="/">Home</Link> | <Link to="/product/1">Product 1</Link>
9      </nav>
10    </header>
11  );
12};
13
14export default Header;

Le pagine

Creiamo una cartella pages in src e creiamo le nostre pagine (componenti).

HomePage.tsx

1import React from 'react';
2
3const HomePage: React.FC = () => {
4  return <h1>Welcome to Our Website</h1>;
5};
6
7export default HomePage;

ProductDetailsPage.tsx

1import React from 'react';
2import { useParams } from 'react-router-dom';
3
4interface RouteParams {
5  productId: string;
6}
7
8const ProductDetailPage: React.FC = () => {
9  let { productId } = useParams<RouteParams>();
10
11  return <h1>Product Detail for Product ID: {productId}</h1>;
12};
13
14export default ProductDetailPage;

NotFoundPage.tsx

1import React from 'react';
2
3const NotFoundPage: React.FC = () => {
4  return <h1>404: Page Not Found</h1>;
5};
6
7export default NotFoundPage;

Aggiorniamo index.ts

1import React from 'react';
2import ReactDOM from 'react-dom';
3import { createBrowserRouter, RouterProvider } from 'react-router-dom';
4import HomePage from './pages/HomePage';
5import ProductDetailPage from './pages/ProductDetailPage';
6import NotFoundPage from './pages/NotFoundPage';
7
8// Creazione del router
9const router = createBrowserRouter([
10  {
11    path: "/",
12    element: <HomePage />,
13  },
14  {
15    path: "/product/:productId",
16    element: <ProductDetailPage />,
17  },
18  {
19    path: "*",
20    element: <NotFoundPage />,
21  },
22]);
23
24ReactDOM.render(
25  <React.StrictMode>
26    <RouterProvider router={router} />
27  </React.StrictMode>,
28  document.getElementById('root')
29);

Questo esempio dimostra l'utilizzo di createBrowserRouter per definire le route. RouterProvider viene poi usato per applicare la configurazione del router all'applicazione.

Note Aggiuntive

  • Lazy Loading: React Router 6.2 facilita anche l'implementazione del lazy loading dei componenti utilizzando React.lazy e import() insieme a createBrowserRouter. Questo può migliorare le prestazioni dell'applicazione caricando i componenti solo quando necessario.

  • Gestione degli Errori: Puoi gestire errori a livello di rotta definendo una rotta di errore utilizzando errorElement nella tua configurazione del router.

Questo approccio moderno alla configurazione del routing in React Router offre una maggiore flessibilità e migliora l'integrazione delle funzionalità avanzate di React, come il lazy loading e la gestione degli errori.

Ma perché fermarci? Aggiungiamo questi due ulteriori aspetti.

Implementare le rotte con il lazy loading

Per utilizzare il lazy loading, useremo la funzione React.lazy per importare i componenti solo quando sono effettivamente richiesti. Questo richiede l'uso di React.Suspense per gestire il rendering dei componenti mentre sono in fase di caricamento.

Aggiorniamo l’index.tsx

1import React, { lazy, Suspense } from 'react';
2import ReactDOM from 'react-dom';
3import { createBrowserRouter, RouterProvider } from 'react-router-dom';
4import Layout from './components/Layout'; // Componente per il layout comune
5
6// Componenti importati con lazy loading
7const HomePage = lazy(() => import('./pages/HomePage'));
8const ProductDetailPage = lazy(() => import('./pages/ProductDetailPage'));
9const NotFoundPage = lazy(() => import('./pages/NotFoundPage'));
10const ErrorPage = lazy(() => import('./pages/ErrorPage')); // Pagina di errore personalizzata
11
12// Creazione del router con gestione degli errori
13const router = createBrowserRouter([
14  {
15    path: "/",
16    element: <Layout />, // Utilizza un layout comune se necessario
17    errorElement: <ErrorPage />, // Gestione degli errori
18    children: [
19      {
20        index: true,
21        element: <HomePage />,
22      },
23      {
24        path: "product/:productId",
25        element: <ProductDetailPage />,
26      },
27      {
28        path: "*",
29        element: <NotFoundPage />,
30      },
31    ],
32  },
33]);
34
35ReactDOM.render(
36  <React.StrictMode>
37    <Suspense fallback={<div>Loading...</div>}>
38      <RouterProvider router={router} />
39    </Suspense>
40  </React.StrictMode>,
41  document.getElementById('root')
42);

In questo esempio, Suspense viene utilizzato per avvolgere l'intera applicazione nel punto di ingresso, fornendo un componente di fallback che viene mostrato mentre i componenti lazy sono in fase di caricamento. errorElement è utilizzato per definire un componente da renderizzare in caso di errori durante la navigazione verso una route specifica.

All’appello qui però mancano due elementi: <Layout /> ed <ErrorPage />.

Implementiamo ErrorPage

Il componente ErrorPage in un'applicazione React che utilizza React Router con errorElement è progettato per visualizzare un messaggio o una UI specifica quando si verifica un errore durante il tentativo di navigare verso una determinata rotta. Questo componente può essere personalizzato per mostrare informazioni utili all'utente, come suggerimenti su cosa fare dopo o un link per tornare alla homepage.

Ecco un esempio base di come potrebbe essere strutturato il componente ErrorPage:

ErrorPage.tsx

1import React from 'react';
2import { useRouteError } from 'react-router-dom';
3
4const ErrorPage: React.FC = () => {
5  const error = useRouteError();
6  console.error(error);
7
8  return (
9    <div>
10      <h1>Something went wrong!</h1>
11      <p>We're sorry, there was an error loading your page.</p>
12      <p>
13        {/* Qui puoi aggiungere dettagli specifici sull'errore se necessario */}
14        <strong>Error Message:</strong> {error.message}
15      </p>
16      {/* Fornisci un link per tornare alla homepage o ad altre parti dell'applicazione */}
17      <a href="/">Go back home</a>
18    </div>
19  );
20};
21
22export default ErrorPage;

In questo esempio, useRouteError è un hook fornito da React Router che consente di accedere all'errore che ha causato il rendering dell'errorElement. Questo può essere utile per diagnosticare il problema o per mostrare messaggi di errore più specifici all'utente.

Il componente ErrorPage visualizza un messaggio generico di errore insieme al messaggio di errore specifico (se disponibile) e fornisce un link per tornare alla homepage. Questo aiuta a migliorare l'esperienza utente offrendo una via d'uscita in caso di errori durante la navigazione.

Puoi personalizzare ulteriormente questo componente in base alle esigenze specifiche della tua applicazione, ad esempio, implementando logica per gestire tipi di errore diversi in modi specifici o fornendo opzioni di navigazione aggiuntive agli utenti.

Il componente Layout

Il componente Layout è spesso utilizzato in applicazioni React per definire una struttura comune a più pagine dell'applicazione, come un'intestazione (header), una barra di navigazione (navbar), un piè di pagina (footer), e altre parti dell'UI che si vogliono mantenere consistenti attraverso diverse route. Ecco come potrebbe essere strutturato un semplice componente Layout che utilizza React Router:

Layout.tsx

Questo componente definisce la struttura base della pagina e include spazi per l'intestazione, il contenuto principale e il piè di pagina. Può anche includere una barra di navigazione con link per la navigazione tra le pagine.

1import React from 'react';
2import { Outlet } from 'react-router-dom';
3import Header from './Header'; // Assumi che esista un componente Header
4import Footer from './Footer'; // Assumi che esista un componente Footer
5
6const Layout: React.FC = () => {
7  return (
8    <div>
9      <Header />
10      {/* Outlet rappresenta il componente che sarà renderizzato dalle route figlie */}
11      <main>
12        <Outlet />
13      </main>
14      <Footer />
15    </div>
16  );
17};
18
19export default Layout;

Spiegazione

  • <Header />: Questo componente potrebbe contenere il logo dell'applicazione, la barra di navigazione con link alle varie pagine dell'applicazione, e altre informazioni utili che si vogliono mostrare in cima a tutte le pagine.

  • <Outlet />: Questo è un componente speciale fornito da React Router che renderizza i componenti dei figli della route corrispondente. In pratica, quando navighi tra le pagine definite nelle route figlie del Layout, il contenuto di queste pagine verrà renderizzato dove si trova l'<Outlet />.

  • <Footer />: Simile all'<Header />, questo componente può contenere informazioni che si vogliono mostrare in fondo a tutte le pagine, come informazioni sull'azienda, link a social media, contatti, ecc.

Utilizzo del Layout nelle Route

Nell'esempio precedente con createBrowserRouter, abbiamo definito il Layout come elemento di una route. Questo approccio consente di avere un layout comune per diverse pagine dell'applicazione, mantenendo il codice pulito e organizzato. Ogni pagina specifica viene caricata all'interno del Layout grazie all'<Outlet />.

Questo modello di design è utile per costruire applicazioni web complesse con React, mantenendo una struttura di navigazione e layout coerente in tutta l'applicazione.

Caricamento...

Diventiamo amici di penna? ✒️

Iscriviti alla newsletter per ricevere una mail ogni paio di settimane con le ultime novità, gli ultimi approfondimenti e gli ultimi corsi gratuiti puubblicati. Ogni tanto potrei scrivere qualcosa di commerciale, ma solo se mi autorizzi, altrimenti non ti disturberò oltre.

Se non ti piace la newsletter ti ricordo la community su Discord, dove puoi chiedere aiuto, fare domande e condividere le tue esperienze (ma soprattutto scambiare due meme con me). Ti aspetto!

Ho in previsione di mandarti una newsletter ogni due settimane e una commerciale quando capita.