Beginnen met React: componenten, props en state
In het vorige hoofdstuk zag je een overzicht van de populairste frameworks. Nu gaan we dieper in op React: het meest gebruikte frontend framework ter wereld. Je leert hoe je een project aanmaakt, hoe componenten werken en hoe je data beheert met state.
Waarom React?
React is gebouwd door Meta (Facebook) en is in 2013 uitgebracht. Sindsdien is het uitgegroeid tot het dominante frontend framework: het heeft het grootste ecosysteem, de meeste beschikbare bibliotheken en de meeste vacatures. Als je met React leert werken, open je een grote deur op de arbeidsmarkt.
Vue is toegankelijker voor absolute beginners. Maar als je snel wil starten met een framework dat overal gevraagd wordt, is React een uitstekende keuze.
Je eerste React-project aanmaken
We gebruiken Vite om het project op te zetten. Vite is een snelle build-tool die je project klaar maakt om in de browser te draaien. Voer deze commando's uit in je terminal:
npm create vite@latest my-app -- --template react
cd my-app
npm install
npm run dev
Na npm run dev opent Vite een lokale server. Ga naar http://localhost:5173 in je browser en je ziet de standaard React-startpagina.
De projectstructuur
Na het aanmaken zie je deze bestanden:
my-app/
index.html ← het HTML-bestand dat de browser laadt
src/
main.jsx ← het startpunt: koppelt React aan index.html
App.jsx ← het hoofdcomponent van je applicatie
index.html bevat één <div id="root">. React vult die div met jouw componenten. In main.jsx staat de koppeling:
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>
)
Je hoeft dit bestand zelden aan te passen. Je werk speelt zich af in App.jsx en de componenten die je zelf aanmaakt.
Componenten
Een component is een herbruikbaar stukje gebruikersinterface. Het is een JavaScript-functie die JSX teruggeeft. Componenten beginnen altijd met een hoofdletter.
function Welcome() {
return (
<div>
<h1>Welkom bij mijn app!</h1>
<p>Dit is mijn eerste React-component.</p>
</div>
)
}
export default Welcome
Importeer en gebruik dit component in App.jsx:
import Welcome from './Welcome.jsx'
function App() {
return (
<div>
<Welcome />
<Welcome />
</div>
)
}
export default App
Je ziet nu twee keer hetzelfde welkomstblok op de pagina. Dat is de kracht van herbruikbaarheid.
JSX
JSX is de HTML-achtige syntax die je in React-componenten schrijft. Het lijkt op HTML, maar het is eigenlijk JavaScript. De browser begrijpt JSX niet rechtstreeks; Vite zet het automatisch om naar gewoon JavaScript.
Er zijn drie belangrijke regels:
1. Altijd één root-element. Een component mag maar één wrapper-element teruggeven. Gebruik een lege tag <>...</> als je geen extra div wil:
function Example() {
return (
<>
<h2>Titel</h2>
<p>Paragraaf</p>
</>
)
}
2. Gebruik className in plaats van class. In JSX is class een gereserveerd woord in JavaScript. Schrijf altijd className:
function Button() {
return <button className="btn-primary">Klik hier</button>
}
3. JavaScript-expressies schrijf je tussen {}:
const name = 'Anna'
function Greeting() {
return (
<p>
Hallo, {name}! Het is nu {new Date().getFullYear()}.
</p>
)
}
Props
Met props geef je data mee aan een component. Props werken als parameters van een functie. Zo maak je een component flexibel en herbruikbaar.
function Card({ title, description }) {
return (
<div className="card">
<h2>{title}</h2>
<p>{description}</p>
</div>
)
}
export default Card
Gebruik dit component met eigen waarden:
import Card from './Card.jsx'
function App() {
return (
<div>
<Card title="Webdesign" description="Mooie interfaces op maat." />
<Card
title="Development"
description="Schaalbare webapplicaties."
/>
</div>
)
}
export default App
Geef een prop een standaardwaarde als die niet altijd verplicht is:
function Card({ title, description = 'Geen beschrijving opgegeven.' }) {
return (
<div className="card">
<h2>{title}</h2>
<p>{description}</p>
</div>
)
}
State met useState
State is data die kan veranderen, zoals de waarde van een invoerveld of de score in een spel. Wanneer state verandert, hertekent React het component automatisch.
Je beheert state met de useState-hook:
import { useState } from 'react'
function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>Aantal klikken: {count}</p>
<button onClick={() => setCount(count + 1)}>Klik!</button>
</div>
)
}
export default Counter
useState(0) geeft twee dingen terug: de huidige waarde (count) en een functie om die waarde te updaten (setCount). Elke keer dat je setCount aanroept, hertekent React het component met de nieuwe waarde.
Als je let aantal = 0 gebruikt en de waarde aanpast, weet React niet dat er iets is veranderd. Alleen via useState triggert een update de hertekening van het component.
Lijsten renderen
Gebruik .map() om een array van items om te zetten naar JSX-elementen. Elk item heeft een key-prop nodig: React gebruikt die om bij te houden welk element welk is.
const fruits = ['Appel', 'Banaan', 'Kers']
function FruitList() {
return (
<ul>
{fruits.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
)
}
export default FruitList
Gebruik een unieke, stabiele waarde als key: een ID uit je database is ideaal. Gebruik zo min mogelijk de index van het array als sleutel, want dat kan problemen geven als de volgorde van items verandert.
Een volledig voorbeeld
Hier is een kleine takenlijst die componenten, props, state en lijsten samenvoegt:
function TaskItem({ text, done, onClick }) {
return (
<li
onClick={onClick}
style={{
textDecoration: done ? 'line-through' : 'none',
cursor: 'pointer',
}}
>
{text}
</li>
)
}
export default TaskItem
import { useState } from 'react'
import TaskItem from './TaskItem.jsx'
const initialTasks = [
{ id: 1, text: 'HTML leren', done: true },
{ id: 2, text: 'CSS leren', done: true },
{ id: 3, text: 'React leren', done: false },
]
function TaskList() {
const [tasks, setTasks] = useState(initialTasks)
function toggleDone(id) {
setTasks(
tasks.map((task) =>
task.id === id ? { ...task, done: !task.done } : task
)
)
}
return (
<div>
<h2>Mijn taken</h2>
<ul>
{tasks.map((task) => (
<TaskItem
key={task.id}
text={task.text}
done={task.done}
onClick={() => toggleDone(task.id)}
/>
))}
</ul>
<p>
{tasks.filter((t) => t.done).length} van {tasks.length} taken
afgerond.
</p>
</div>
)
}
export default TaskList
Gebruik TaskList in App.jsx:
import TaskList from './TaskList.jsx'
function App() {
return (
<div
style={{
maxWidth: '480px',
margin: '2rem auto',
fontFamily: 'system-ui',
}}
>
<h1>React takenlijst</h1>
<TaskList />
</div>
)
}
export default App
Klik op een taak om hem af te strepen. React hertekent de lijst automatisch elke keer dat de state verandert.
Volgende stap
Je kent nu de kern van React: componenten, JSX, props, state en lijsten. De logische volgende stap is Next.js: een framework gebouwd bovenop React dat server-side rendering, bestandsgebaseerde routing en een ingebouwde API-laag toevoegt. Next.js is de standaard keuze voor productie-klare React-applicaties.