Una ruta és un "mapping" entre una URL i un component

Introducció

React Router és una biblioteca que et permet crear rutes.

Una ruta és un "mapping" entre el path d'una URL i un component:

flowchart LR
    Path --route--> Component

Aquest tipus de navegació s'anomena "client-site routing" perquè el navegador no mostra pàgines generades des del servidor, sinó que estat navegant d'un component a l'altre dins de l'aplicació.

En aquest enllaç tens el projecte de suport: https://gitlab.com/xtec/typescript/react-router

Entorn de treball

Crea un projecte

$ bun create vite react-router --template react-swc-ts
$ bun install react-bootstrap bootstrap

Instal.la la biblioteca react-router-dom:

$ bun install react-router-dom

Observació. Utilitzem la versió v6 !

Route

Modifica el fitxer App.tsx.

A continuació tens dues rutes: / i /student:

import {BrowserRouter, Routes, Route } from "react-router-dom"

export default function App() {

  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/student" element={<Student/>} />
      </Routes>
    </BrowserRouter>
  )
}

function Home() {
  return <h1>Home</h1>
}

function Student() {
  return <h1>Student</h1>
}

Pots verificar que:

URL Path Component
http://localhost:5173/ / <Home/>
http://localhost:5173/student /student <Student/>

Segment dinamic

Si vols pots utilitzar parametres al path.

Crea el fitxer data.ts amb alguns estudiants:

export type Student = {
  id: number
  name: string
  surname: string
}

export const students: Student[] = [
  { id: 1, name: "Mary", surname: "Sinclair" },
  { id: 3, name: "Olivia", surname: "Hart" }
]

El component <Student/> pot utilitzar aquest parametres mitjançant el hook useParams:

import { BrowserRouter, Routes, Route, useParams } from "react-router-dom"
import {students} from "./data"

export default function App() {

  return (

      <BrowserRouter>
        <Routes>
          <Route path="/student/:id" element={<Student />} />
        </Routes>
      </BrowserRouter>
  )
}

function Student() {

  const { id } = useParams()
  
  const student = students.find(student => student.id == Number(id))
  if (student == null) {
    return <p>Student not found!</p>
  }
  
  return <p>{student.name} {student.surname}</p>
}

Pots veure que ara React respon a http://localhost:5173/student/1 amb el nom de l'estudiant.

Pots crear enllaços amb <a>.

Quan l'usuari fa clic a l'enllaç, l'usuari navega al path que s'ha especificat dins el component <route> i es renderitza el component que fa "match".

A continuació crea un component <Students> que mostra una llista de tots els estudiants amb un enllaç a cada estudiant:

import { BrowserRouter, Routes, Route, useParams } from "react-router-dom"
import { students } from "./data"

export default function App() {

  return (

    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home/>}/>
        <Route path="/student/" element={<Students />} />
        <Route path="/student/:id" element={<Student />} />
      </Routes>
    </BrowserRouter>
  )
}

function Students() {

  return (
    <div className="container">
      <h3>Students</h3>
      <table className="table">
        <tr><th>Surname</th><th>Name</th></tr>
        {students.map(student => (
          <tr>
            <td><a href={"/student/" + student.id}>{student.surname}</a></td>
            <td>{student.name}</td>
          </tr>)
        )}
      </table>
    </div>
  )
}

Activitat

1.- Crea una barra de navegació compartida per totes les "pagines".

// ...
import Container from 'react-bootstrap/Container';
import Nav from 'react-bootstrap/Nav';
import Navbar from 'react-bootstrap/Navbar';

// ...

function Menu() {
  return <Navbar bg="primary" data-bs-theme="dark">
    <Container>
      <Navbar.Brand href="/">School</Navbar.Brand>
      <Nav className="me-auto">
        <Nav.Link href="/">Home</Nav.Link>
        <Nav.Link href="/student/">Students</Nav.Link>
      </Nav>
    </Container>
  </Navbar>
}

function Home() {
  return (
    <>
      <Menu />
      <p>Escola Patufet</p>
    </>
  )
}

// ...

2.- Afegeix una ruta "Not Found"

export default function App() {

  return (

    <BrowserRouter>
      <Routes>
        <Route path="*" element={<NotFound />} />
        <Route path="/" element={<Home />} />
        // ..

3.- Fes els exemples de https://www.freecodecamp.org/news/use-dynamic-segments-in-react-router/

TODO