Waarom loading & error states?
Je WorkoutList uit de vorige stap haalt netjes data op. Maar wat ziet de gebruiker terwijl
die fetch onderweg is? Niets. Een lege pagina. En als de backend offline is? Ook
niets. Of erger: een crash.
Een goede UI laat altijd weten wat er gebeurt:
Drie momenten, drie schermen
- Bezig met laden → "Laden..."
- Iets misgegaan → foutmelding tonen
- Klaar → de echte data tonen
Drie states naast elkaar
Je hebt drie stukjes state nodig in je WorkoutList:
const [workouts, setWorkouts] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
workouts— de array die je toont. Begint leeg.isLoading—truetijdens fetch,falsedaarna. Begint true omdat de fetch direct start.error—nullals alles goed gaat, een tekst bij een fout.
WorkoutList uitbreiden
Je vult je bestaande WorkoutList aan met de twee extra states en een try/catch
rond de fetch:
// frontend/src/components/WorkoutList.jsx
import { useEffect, useState } from 'react';
import Workout from './Workout';
function WorkoutList() {
const [workouts, setWorkouts] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchWorkouts = async () => {
try {
const response = await fetch('http://localhost:4000/api/workouts');
if (!response.ok) {
throw new Error('Kon workouts niet ophalen');
}
const data = await response.json();
setWorkouts(data);
} catch (err) {
setError(err.message);
} finally {
setIsLoading(false);
}
};
fetchWorkouts();
}, []);
if (isLoading) {
return <p>Laden...</p>;
}
if (error) {
return <p className="error">Er ging iets mis: {error}</p>;
}
return (
<div className="workout-list">
{workouts.length === 0
? <p>Geen workouts gevonden.</p>
: workouts.map(workout => (
<Workout key={workout._id} workout={workout} />
))}
</div>
);
}
export default WorkoutList;
try { ... } catch (err) { ... } finally { ... }— vangt netwerkfouten af én zorgt datisLoadingsowieso opfalsekomt.if (!response.ok)— fetch throwt niet bij een 404 of 500. Je moet zelf checken en een error gooien.setError(err.message)— bewaart de foutmelding zodat je hem in de UI kunt tonen.finally— draait altijd, of het nu goed of fout ging. Perfect omisLoadinguit te zetten.
Conditioneel renderen
Onderaan zie je drie return-blokken. React rendert het eerste blok dat van toepassing is en
stopt daar. Dat heet early return.
if (isLoading) return <p>Laden...</p>;
if (error) return <p className="error">{error}</p>;
// alleen hier kom je als alles goed ging
return <div>...</div>;
Volgorde is belangrijk
Eerst isLoading, dan error, dan de echte UI. Andersom kun je de error niet
tonen omdat workouts dan al leeg is.
Testen of het werkt
Loading testen
Open DevTools → tab Network → zet Throttling op Slow 3G. Refresh
de pagina — je ziet "Laden..." een paar seconden.
Error testen
Stop je backend (Ctrl+C in terminal 1). Refresh de frontend. Je ziet nu de foutmelding in plaats van een lege pagina.
Veelgemaakte fouten
1. isLoading start op false
Dan flashed de gebruiker even "Geen workouts gevonden" voor de echte data binnen is. Start altijd op
true.
2. setIsLoading(false) alleen in try
Dan blijft de loading-spinner hangen bij een error. Gebruik finally, of zet hem in beide
takken.
3. response.ok niet checken
Een 404 of 500 belandt gewoon in .then(). Check eerst of de response oké is, anders gooi
je geen error en zie je nooit wat er fout ging.
4. De error ergens in de console laten staan
Gebruikers openen geen DevTools. Toon de fout altijd in de UI.
Volgende Stap
Lezen werkt netjes. Tijd om gebruikers ook nieuwe data te laten toevoegen.
Controlled inputs en een POST-request naar je backend