Introductie
Deze opdrachten vormen samen één doorlopend project: een Student Planner. In plaats van telkens een nieuwe oefening te starten, breid je stap voor stap dezelfde app uit.
Hoofdidee: je bouwt per niveau verder aan dezelfde app. Zo blijft de context hetzelfde en zie je beter hoe losse React-onderdelen samen één echte applicatie vormen.
Wat bouw je precies?
Je maakt een Student Planner: een app waarin een student schooltaken kan bijhouden. Denk aan een dashboard met taken, filters en een detailpagina per taak.
Dit moet er minimaal in komen:
- Een dashboard met een takenlijst
- Taken kunnen toevoegen via een formulier
- Taken filteren (bijvoorbeeld Alles, Frontend, Backend)
- Taken markeren als afgerond of nog te doen
- Zoeken in taken
- Taken bewaren in localStorage
- Meerdere pagina's met React Router (dashboard, login, taakdetail)
Nog niet nodig bij de start:
- Geen backend of database
- Geen echte login met server
- Geen perfecte styling
Hoe werk je deze opdrachten uit?
- Gebruik één React oefenproject voor alle niveaus van deze Student Planner
- Breid per niveau je bestaande code uit in plaats van opnieuw te beginnen
- Maak binnen hetzelfde project aparte componenten, pagina's en folders zodat je structuur netjes blijft
- Begin klein: eerst layout, daarna state, daarna interactie
- Gebruik de theorie-links als je vastloopt
- Werk per opdracht in losse componenten, niet alles in App.jsx
- Test steeds tussendoor in de browser en in de console
Styling door de hele app
Je werkt gedurende alle niveaus aan de styling van je app. Per niveau staan er kleine styling-doelen die je meeneemt — de styling groeit dus mee met de functionaliteit. Aan het eind maak je in niveau 7 de puntjes op de i.
Kies je eigen aanpak: je mag zelf kiezen of je werkt met gewone CSS
(CSS-bestanden per component, bijvoorbeeld TaskCard.css) of met
Tailwind CSS (utility classes in de JSX). Beide zijn prima, kies wat jou
het meeste aanspreekt. Wissel niet halverwege.
Voorstel projectstructuur
react-opdrachten/
├── src/
│ ├── components/
│ │ ├── Header.jsx
│ │ ├── Sidebar.jsx
│ │ ├── FilterBar.jsx
│ │ ├── TaskList.jsx
│ │ ├── TaskCard.jsx
│ │ ├── TaskForm.jsx
│ │ ├── QuotesSection.jsx
│ │ └── Panel.jsx
│ ├── pages/
│ │ ├── Dashboard.jsx
│ │ ├── Login.jsx
│ │ ├── TaskDetail.jsx
│ │ └── DocentView.jsx
│ ├── context/
│ │ └── AuthContext.jsx
│ ├── data/
│ ├── App.jsx
│ └── main.jsx
Niveau 1: Basisopzet van de Student Planner
1.1 Maak je project aan
Maak een nieuw React-project met Vite. Verwijder daarna alle demo-inhoud die Vite automatisch aanmaakt, zodat je met een schone lei begint.
Wat moet je zien: een lege pagina met alleen de tekst Student Planner.
npm run dev werkt en de browser toont alleen de titel, zonder
Vite-voorbeeldcontent.
1.2 Maak je eerste component: TaskCard
Maak een apart bestand voor een TaskCard component. Dit component toont de informatie van één
taak: de naam, het vak, de deadline en de status.
Wat moet je zien: een kaart op de pagina met bijvoorbeeld:
- Naam: React presentatie
- Vak: Frontend
- Deadline: 15 juni
- Status: Nog niet klaar
1.3 Zet de basisstructuur van je app op
Maak nu ook een Header en een Sidebar als aparte componentbestanden. Zorg dat
alle drie de componenten samen zichtbaar zijn op de pagina.
Wat moet je zien: een pagina met bovenaan een header met de naam van de app, een sidebar
met navigatie-items zoals Dashboard en Login, en de TaskCard uit de
vorige opdracht.
🎨 Styling-doel: geef je layout een eerste vorm. De header staat bovenaan, de sidebar links of rechts, en de TaskCard heeft een duidelijke kaart-uitstraling (rand of achtergrondkleur). Kies je eigen stijl — netjes is genoeg, mooi hoeft nog niet.
Niveau 2: Components & Props
2.1 Breid je componentenstructuur uit
Voeg twee nieuwe componenten toe aan je project: een FilterBar en een TaskList.
Gebruik ze allebei op je dashboardpagina.
Wat moet er in de componenten komen:
FilterBar: een rij met drie knoppen — Alles, Frontend en Backend. De knoppen hoeven nog niets te doen, ze moeten alleen zichtbaar zijn.TaskList: een container die één of meerdereTaskCard-componenten in zich heeft. Zet er voorlopig twee of drieTaskCard's in met vaste inhoud.
Wat moet je zien: onder je Header verschijnt de FilterBar
met drie knoppen, en daaronder de TaskList met meerdere TaskCard's erin.
FilterBar en TaskList staan elk in een eigen bestand
en worden geïmporteerd in je dashboard.
2.2 Werk met props
Pas TaskCard aan zodat hij de taakgegevens ontvangt via props in plaats van dat de gegevens
hardcoded in het component staan. Gebruik meteen destructuring in de parameters van
de functie, zodat je velden zoals titel en status direct kunt gebruiken
zonder props.titel of props.status. Render daarna minstens drie verschillende
taken met hetzelfde component.
Wat moet je zien: drie taakkaarten met elk andere inhoud, allemaal gemaakt met hetzelfde
TaskCard component. Bijvoorbeeld:
- Kaart 1: React presentatie — Frontend — 15 juni — Nog niet klaar
- Kaart 2: Database ontwerp — Backend — 20 juni — Afgerond
- Kaart 3: UI prototype — Design — 22 juni — Nog niet klaar
props. komt nergens voor in je TaskCard, en er staat niets meer hardcoded in het
component.
🎨 Styling-doel: geef TaskCard een duidelijke opmaak met padding, een
rand of schaduw, en zorg dat de velden (titel, vak, deadline, status) leesbaar gestructureerd
zijn — bijvoorbeeld de titel dikker en groter dan de rest.
2.3 Gebruik children
Maak een herbruikbare Panel component met een titel en een ruimte voor willekeurige inhoud
via children. Gebruik dit component op minstens drie plekken met steeds andere inhoud.
Wat moet je zien: drie panelen op de pagina, elk met een andere titel en andere
binneninhoud. Bijvoorbeeld een profielblok, een melding over deadlines en een tip van de dag — allemaal
gebouwd met hetzelfde Panel component.
Panel component dat je minstens drie keer gebruikt
met verschillende inhoud erin.
2.4 Bouw een eerste takenoverzicht
Maak een array met taakobjecten en render voor elk object een TaskCard. De gegevens geef je
door via props. Je hoeft in deze stap nog geen unieke key toe te voegen — een
console-waarschuwing over keys mag er nog zijn. In niveau 4 lossen we dat op.
Wat moet je zien: een lijst van minstens drie taakkaarten die automatisch gegenereerd worden vanuit de array. Je hebt de kaarten dus niet drie keer handmatig in JSX geschreven.
Niveau 3: Interactie in de Student Planner
3.1 Maak een status-toggle
Voeg bij elke taakkaart een knop toe waarmee je de status van de taak wisselt tussen afgerond en niet afgerond.
Wat moet je zien: als je op de knop klikt, verandert de tekst of stijl van de taak direct. Bijvoorbeeld van Nog niet klaar naar Afgerond en weer terug. Je hoeft de pagina niet te refreshen.
Tip: voor nu mag elke TaskCard z'n eigen lokale status-state hebben.
In niveau 4 tillen we dit omhoog naar de lijst, zodat je ook kunt filteren op status.
3.2 Toggle een detailpaneel
Voeg aan elke taakkaart een knop Toon details toe. Als je erop klikt, verschijnt extra informatie over die taak in de kaart zelf. Klik je nog een keer, dan verdwijnt de informatie weer.
Wat moet je zien: bij een klik klapt er binnen de kaart een klein stukje extra informatie open, zoals een korte omschrijving of een tip. Een tweede klik sluit het weer.
Let op: dit is een simpele inline-toggle binnen de kaart — geen aparte detailpagina. In niveau 6 bouw je pas een echte detailpagina met een eigen URL en alle gegevens van de taak.
3.3 Kies een actieve filterknop
Maak drie knoppen: Alles, Te doen en Afgerond. De knop die je aanklikt moet er visueel anders uitzien dan de andere twee.
Wat moet je zien: de actieve knop heeft een andere kleur of stijl. Als je op een andere knop klikt, wisselt de actieve stijl mee.
Let op: de takenlijst hoeft in deze stap nog niet echt gefilterd te worden. We oefenen hier alleen met state en conditionele styling — het échte filteren van de lijst komt in niveau 4. Zo houd je deze stap klein en overzichtelijk.
🎨 Styling-doel: zorg dat het verschil tussen actieve en inactieve knoppen duidelijk zichtbaar is. Denk aan een andere achtergrondkleur, een rand of dikkere tekst voor de actieve knop.
3.4 Live input preview
Maak een invoerveld waarin een gebruiker de naam van een nieuwe taak kan typen. Onder het veld verschijnt meteen een preview van wat er getypt wordt.
Wat moet je zien: terwijl je typt verschijnt er onder het veld bijvoorbeeld: Nieuwe taak: React opdracht afmaken. De preview past zich aan bij elke toetsaanslag.
3.5 Bouw een uitklapbaar zijpaneel
Maak een zijpaneel met extra informatie, zoals profielinfo, statistieken of een tip. Het paneel moet open en dicht kunnen via een knop.
Wat moet je zien: een knop waarmee het zijpaneel zichtbaar en onzichtbaar wordt. Het paneel is standaard gesloten.
Niveau 4: Taken beheren
4.1 Render een lijst met keys
Maak een array met taakobjecten en render ze als een lijst of grid op de pagina. Elk item in de lijst
heeft een unieke id die je gebruikt als key.
Wat moet je zien: minstens vier taakkaarten die automatisch uit de array worden gegenereerd.
4.2 Filter op categorie
Voeg filterknoppen toe boven je takenlijst, bijvoorbeeld Alles, Frontend en Backend. Als je op een knop klikt, zie je alleen de taken uit die categorie.
Wat moet je zien: klik je op Frontend, dan verdwijnen de backend-taken uit de lijst. Klik je op Alles, dan zijn alle taken weer zichtbaar.
4.3 Maak een controlled form
Bouw een formulier waarmee een student een nieuwe taak kan toevoegen. Na het invullen en versturen verschijnt de nieuwe taak meteen in de lijst.
Wat moet je zien: een formulier met minimaal een invoerveld voor de taaknaam en een knop Toevoegen. Na het klikken op de knop verschijnt de nieuwe taak onderaan de lijst en is het invoerveld weer leeg.
Let op: de pagina mag niet refreshen bij het versturen van het formulier.
4.4 Werk met meerdere formvelden in één object
Breid je taakformulier uit met extra velden: titel, vak, deadline en prioriteit. Sla alle velden op in één state-object in plaats van losse state-variabelen.
Wat moet je zien: een formulier met vier invulvelden. Na het versturen bevat de nieuwe taakkaart al deze gegevens.
4.5 Voeg validatie toe
Zorg dat het formulier een foutmelding toont in drie situaties:
- Een verplicht veld (zoals de taaknaam) is leeg.
- De deadline is geen geldige datum.
- De deadline ligt in het verleden.
De taak mag pas worden toegevoegd als alle invoer correct is.
Wat moet je zien:
- Laat je het titelveld leeg en klik je op Toevoegen, dan verschijnt er een duidelijke foutmelding zoals Vul een taaknaam in.
- Vul je een datum in die in het verleden ligt, dan verschijnt er een melding zoals Deadline mag niet in het verleden liggen.
- Laat je het deadlineveld leeg of vul je iets ongeldigs in, dan verschijnt er een melding zoals Vul een geldige deadline in.
In alle drie de gevallen wordt de taak niet toegevoegd.
4.6 Combineer alles in één takenmodule
Breng je takenlijst, filterknoppen, formulier en statustoggle samen op één scherm. Voeg ook een melding toe die verschijnt als er nog geen taken zijn.
Wat moet je zien: één werkend scherm waarop een student taken kan toevoegen, de lijst kan zien, kan filteren op categorie, en taken kan afvinken. Als de lijst leeg is staat er een melding zoals Nog geen taken toegevoegd.
🎨 Styling-doel: zorg dat afgeronde taken visueel anders ogen dan open taken. Bijvoorbeeld een doorgestreepte titel, een groene rand, of een lichtere achtergrondkleur. Zo zie je in één oogopslag wat klaar is.
Niveau 5: Data & Bewaren
5.1 Bewaar taken in localStorage
Zorg dat de takenlijst bewaard blijft als de gebruiker de pagina refresht of de browser sluit.
Wat moet je zien: voeg een taak toe, refresh de browser, en de taak staat er nog steeds.
5.2 Fetch quotes van een API
Voeg een nieuw component QuotesSection toe aan je dashboard. In dit blok toon je
motiverende quotes voor studenten, opgehaald van de DummyJSON API. Het blok staat naast of onder je
eigen takenlijst.
Gebruik deze API:
https://dummyjson.com/quotes?limit=10
. Het antwoord is een object met een quotes-array. Elke quote heeft een
id, quote (de tekst) en author.
Let op: dit blok staat volledig los van je eigen takenlijst. De quotes worden puur opgehaald en getoond — je kunt ze niet bewerken, afvinken of koppelen aan taken. Het doel van deze opdracht is dat je leert hoe je data ophaalt uit een API en toont.
Wat moet je zien: op het dashboard verschijnt een apart blok met minstens tien quotes, elk met de tekst en de auteur eronder. De data wordt opgehaald bij het laden van het dashboard.
🎨 Styling-doel: geef het quotes-blok een eigen uitstraling zodat het duidelijk losstaat van je takenlijst. Denk aan een andere achtergrondkleur of rand, en maak de quote zelf prominent met de auteur wat kleiner eronder.
5.3 Voeg loading en error states toe
Breid opdracht 5.2 uit met drie extra situaties in het quotes-blok: een laadmelding terwijl de data wordt opgehaald, een foutmelding als het ophalen mislukt, en een melding als er geen quotes zijn.
Wat moet je zien:
- Tijdens het laden: Laden...
- Bij een fout: een foutmelding
- Als er geen quotes zijn: Geen quotes gevonden
Tip voor het testen: om een foutmelding te zien, kun je tijdelijk de URL in je
fetch-aanroep kapot maken (bijvoorbeeld dummyjson.com/quotez). Vergeet niet om hem
daarna weer terug te zetten.
5.4 Bewaar voorkeuren van de gebruiker
Maak een voorkeur die bewaard blijft na het refreshen van de pagina. Kies er één: een dark mode toggle of een sorteervolgorde voor de takenlijst.
Wat moet je zien: zet dark mode aan, refresh de pagina, en de app staat nog steeds in dark mode. Of: kies een sortering, refresh, en de sortering is bewaard.
5.5 Bouw een zoekcomponent
Maak een zoekveld waarmee een student door de takenlijst kan zoeken. De lijst past zich aan terwijl de gebruiker typt. Als er geen resultaten zijn, verschijnt er een melding.
Wat moet je zien: typ je react in het zoekveld, dan zie je alleen taken met dat woord in de naam. Typ je iets wat nergens in voorkomt, dan staat er Geen taken gevonden.
Niveau 6: Routing & Login
6.1 Maak meerdere pagina's
Bouw je app uit naar meerdere pagina's: een dashboardpagina, een taakdetailpagina en een loginpagina. Voeg een navigatiebalk toe zodat je tussen de pagina's kunt wisselen.
Wat moet je zien: je kunt via klikken in de navigatiebalk wisselen tussen minstens drie pagina's, zonder dat de browser ververst.
Optionele uitbreiding: je kunt ook je QuotesSection uit niveau 5
verhuizen naar een eigen /quotes-pagina in plaats van dat het blok op het dashboard
staat. Dan heb je meteen een vierde pagina waartussen je kunt navigeren.
🎨 Styling-doel: geef je navigatiebalk een herkenbare styling en laat duidelijk zien op welke pagina de gebruiker zich bevindt (bijvoorbeeld door de actieve link anders te stylen).
6.2 Werk met URL parameters
Maak de takenlijst klikbaar. Als je op een taak klikt, ga je naar een detailpagina met de ID van die taak in de URL. Op de detailpagina zie je de volledige informatie van die taak.
Wat moet je zien: klik je op taak 3, dan ga je naar een URL zoals /tasks/3.
Op die pagina staan de naam, het vak, de deadline en de omschrijving van die specifieke taak.
6.3 Navigeer programmatisch
Maak een loginformulier met minimaal een veld voor gebruikersnaam en een veld voor wachtwoord. Na het versturen navigeert de app automatisch naar het dashboard, zonder dat de gebruiker op een link hoeft te klikken.
Wat moet je zien: vul het loginformulier in en klik op Inloggen. De app stuurt je automatisch naar de dashboardpagina.
Houd het simpel: je hoeft de ingevulde gebruikersnaam en het wachtwoord nog niet te
controleren — elke invoer mag meteen doorsturen naar het dashboard. Het doel van deze stap is dat je
een formulier via onSubmit kunt verbinden met useNavigate. In de volgende
opdracht maken we hier echte login-logica van met een auth context.
useNavigate.
6.4 Maak een simpele auth context
Bouw een context die bijhoudt of een gebruiker ingelogd is én wat de gebruikersnaam is. De navigatiebalk
toont andere opties afhankelijk van de inlogstatus. Bewaar de inlogstatus en de gebruikersnaam ook in
localStorage, zodat de gebruiker na een refresh ingelogd blijft.
Pas opdracht 6.3 aan: bij het versturen van het loginformulier zet je de gebruikersnaam in de context (en dus ook in localStorage) voordat je doornavigeert.
Wat moet je zien:
- Niet ingelogd: de navigatiebalk toont alleen Login (eventueel plus een publieke pagina zoals Quotes, als je die hebt)
- Wel ingelogd: de navigatiebalk toont Dashboard en Uitloggen
- Refresh na login: je blijft ingelogd, de navigatiebalk wijzigt niet
Welke pagina's waar: het dashboard is alleen voor ingelogde gebruikers (dat maken we af in 6.5). Andere pagina's zoals een quotes-pagina mag je zelf beslissen: altijd zichtbaar of alleen na login.
6.5 Bescherm een route
Zorg dat de dashboardpagina alleen zichtbaar is voor ingelogde gebruikers. Niet-ingelogde gebruikers worden automatisch doorgestuurd naar de loginpagina.
Wat moet je zien: log uit, typ /dashboard handmatig in de adresbalk, en
je komt automatisch op de loginpagina terecht in plaats van het dashboard.
Niveau 7: Einduitbreidingen
7.1 Voeg statistieken toe
Toon boven of naast je takenlijst een aantal statistieken over de taken in de app.
Wat moet je zien: minstens drie statistiekblokken, bijvoorbeeld:
- 5 taken open
- 3 taken afgerond
- Frontend heeft de meeste deadlines
7.2 Voeg sortering en extra filters toe
Geef de gebruiker de mogelijkheid om de takenlijst te sorteren en extra te filteren. Kies minimaal twee uitbreidingen.
Voorbeelden:
- Sorteren op deadline (vroegste eerst)
- Sorteren op prioriteit (hoog naar laag)
- Filteren op taken van deze week
- Filteren op vak
7.3 Maak een docentweergave
Voeg een extra pagina of modus toe waarop een docent een overzicht ziet van alle taken en hun status. In deze weergave kan de docent niet bewerken — het is puur een leesoverzicht.
Wat moet je zien: een aparte pagina of knop Docentmodus die een overzicht toont van alle taken met per taak minimaal: de titel, het vak, de deadline, en de status (Afgerond of Te doen). Bovenaan staan ook samenvattende cijfers, bijvoorbeeld 8 taken totaal — 3 afgerond, 5 open.
Houd het simpel: een knop in de navigatiebalk of een extra route
(zoals /docent) is genoeg. Je hoeft geen aparte docent-login of gebruikersdatabase te
bouwen — deze weergave is beschikbaar voor elke ingelogde gebruiker.
7.4 Maak de styling af
Je hebt tijdens de vorige niveaus al stap voor stap aan styling gewerkt. In deze opdracht poets je de app op tot een geheel dat er samenhangend uitziet. Loop je app door vanaf de loginpagina tot en met de docentweergave en zorg dat alles er consistent uitziet.
Wat moet je zien:
- Eén herkenbaar kleurenpalet door de hele app (bijvoorbeeld twee à drie hoofdkleuren).
- Consistente afstanden, lettergroottes en knopstijlen tussen pagina's.
- De app werkt ook goed op een kleiner scherm (responsive).
- Foutmeldingen, status-indicatoren en actieve knoppen vallen duidelijk op.
Je werkt met wat je aan het begin hebt gekozen: gewone CSS of Tailwind. Voeg in deze stap geen nieuwe stylingmethode toe — polish wat je hebt.
7.5 Eindchallenge
Voeg zelf minstens drie extra features toe aan je Student Planner. Kies features die voor jou nuttig of interessant zijn.
Voorbeelden van extra features:
- Kleurcodes per vak
- Favorieten markeren
- Notificatie als een deadline nadert
- Kalenderweergave van deadlines
- Taken kunnen bewerken na aanmaken
Wat moet je kunnen laten zien: welke drie features je hebt toegevoegd, waarom je ze hebt gekozen en wat ze doen in de app.