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
eimport()
insieme acreateBrowserRouter
. 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 delLayout
, 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!