Routers en Paginas
Tot nu toe hebben we altijd gewerkt met 1 pagina, maar uiteraard bestaan de meeste web applicaties uit verschillende pagina's. Je hebt bijvoorbeeld een lijst pagina waar de data in een lijst wordt getoond, als je dan doorklikt wil je naar een detail pagina gaan. Je wil ook verschillende pagina's gaan aanbieden op andere url's. Zo zal een lijst bijvoorbeeld op het pad /list staan en de detail op /detail/{id}. Om dit te doen gaan we gebruik maken van een externe library uit de npm registry: react-router-dom
Lifting state up
Het eerste wat we gaan doen is onze games list pagina in een apart component plaatsen, zodat deze code niet meer in de App component staat. Deze component krijgt later de verantwoordelijkheid voor het tonen van de verschillende pagina's, niet alleen de List pagina. We maken een nieuwe directory pages en maken daar een nieuwe directory ListPage aan. We kopieren de inhoud van het App.tsx bestand naar een nieuw bestand genaamd ListPage.tsx en doen hetzelfde met de CSS-module van dit component. Vergeet niet de naam van het component aan te passen de default export.
Momenteel zit de lijst van games nog in het ListPage component. We willen dit component beschikbaar maken voor alle pagina's dus we gaan de state een niveau hoger plaatsen. Wat wil zeggen dat we deze gaan terug plaatsen in het App component. We moeten er voor zorgen dat de ListPage de games list via props laten binnen krijgen. We definiëren de volgende props voor de ListPage
interface ListPageProps {
games: Game[],
handleAdd: (game: Game) => void
}Je merkt op dat we hier ook de handleAdd callback handler hebben opgegeven als property van onze ListPage. De handleAdd callback handler die hier wordt meegegeven wordt gewoon doorgeven aan het InputView component.
import InputView from 'components/InputView/InputView';
import List from 'components/List/List';
import React from 'react';
import { Game } from 'types';
import styles from './ListPage.module.css';
interface ListPageProps {
games: Game[],
handleAdd: (game: Game) => void
}
const ListPage = ({games,handleAdd} : ListPageProps) => {
return (
<div>
<List games={games} />
<InputView onAdd={handleAdd} />
</div>
);
}
export default ListPage;En het App component zal er als volgt uit zien.
Merk op dat we de Header component in de App component hebben gelaten. We willen de header op elke pagina plaatsen dus we zetten deze dan op dit niveau.
Nu hebben we er voor gezorgd dat we een aparte pagina hebben voor onze lijst van games en dat het App component verantwoordelijk is voor de lijst van games te beheren (de state bevind zich dus op het hoogste component)
React Router
Nu we een aparte pagina hebben voor de lijst gaan we nu de library installeren die het mogelijk maakt om eenvoudig nieuwe pagina's op verschillende routes te introduceren. We installeren react-router met het volgende commando:
Ondertussen is react-router v6 uitgebracht. Dit betekent dat deze instructies niet allemaal nog gelden voor de laatste nieuwe versie. Daarom kan je best v5 installeren.
Omdat we momenteel maar pagina hebben maken we een heel eenvoudige HomePage.
De CSS style van de welcomeText mag je zelf kiezen. Zorg ervoor dat beide bestanden in een src/Pages/HomePage directory zitten.
Nu gaan we onze App component aanpassen zodat het de React router library gebruikt om de routes te vast te leggen en te kiezen welke page moet getoond worden bij welke route.
Als je ergens React Router wil gebruiken dan moet het parent component altijd een Router component zijn.
Er zijn een aantal varianten op deze Router component zoals BrowserRouter en HashRouter. Deze hebben invloed over hoe de urls die worden gegenereerd voor de paden zullen getoond worden. We bekijken deze niet in detail, maar deze zijn belangrijk als je uiteindelijk je applicatie op een externe webserver wil laten lopen.
Route en Switch noemen we route matching componenten. Als een Switch wordt gerendered, wordt er in zijn kind elementen gezocht achter Route elementen en wordt er gezocht achter het pad dat overeenkomt met de huidige URL. Als het er een vindt, dan rendered hij die Route en negeert hij alle anderen. Dit betekent dat je altijd de meest specifieke (vaak de langste) eerst moet plaatsen voor de minder specifieke routes.
In ons geval hebben we nu twee routes. De route voor de lijst op /list en de route voor / die de HomePage zal laten zien aan de gebruiker. In de Route componenten plaatsen we hier de componenten die hij zal moeten tonen als naar die route gegaan wordt in je browser.
React Router biedt een <Link> component aan om links te maken in je applicatie. Overal waar je een Link rendered wordt een anchor (<a>) tag gerendered in je HTML document.
Je hebt ook nog een speciale versie van de <Link> component die zichzelf als 'actief' kan renderen als de to prop overeenkomt met de huidige locatie. Als je de exacte locatie wilt matchen moet je hierbij ook nog exact als prop meegeven.
Zo kunnen we nu een navigatie balk aanmaken in onze header component:
URL Parameters
Tot nu toe hebben we altijd routes gebruikt die exacte paden voorstellen. Soms wil je ook aan de hand van de url bepaalde parameters gaan meegeven. Zo willen wij in ons voorbeeld een pad aanmaken waarmee je het detail van een game kan bekijken. We zouden hier graag een url zoals /detail/:id toelaten waarbij de :id dus een parameter is. Deze kan bijvoorbeeld /detail/1 of /detail/2 zijn en hiervoor moet altijd hetzelfde component gerendered worden.
Laten we eerst een eenvoudige DetailPage maken voor deze route:
We moeten dan deze DetailPage toevoegen aan onze Router
Een parameter in een route wordt aangeven met de naam van de parameter en een : ervoor. In dit geval is dit /detail/:id waarvan id de naam van de parameter is.
Om deze parameters uit te kunnen lezen in de DetailPage kunnen we de useParams hook gebruiken om deze parameters te kunnen uitlezen.
We kunnen ons ListItem component aanpassen aan de hand van het Link component zodat als we op het de game klikken dat we dan naar de detailpagina verwezen worden.
Last updated
Was this helpful?