

React Basics

Opwarmoefening
Facebook likes
- Toon in de browser wie een bericht leuk vindt op basis van een array namen. Bij elke klik wordt een nieuwe naam toegevoegd en moet de UI handmatig geüpdatet worden.
<div id="likes">
<span class="icon">❤️</span>
<span id="likes-text"></span>
</div>
<button id="add">Add like</button>index.html

Opwarmoefening
Vereisten:
-
Schrijf een functie
likes(names)die een array van namen ontvangt -
De functie retourneert een correcte tekst a.d.h.v length zoals:
-
No one likes this -
Peter likes this -
Peter and Sarah like this -
Peter, Sarah and 2 others like this.
-

Opwarmoefening
Vereisten:
-
Toon deze tekst in de browser
-
Wanneer je op “Add like” klikt:
-
wordt een willekeurige naam toegevoegd aan de array
-
wordt de UI manueel opnieuw gerenderd met een functie
render()
-

Opwarmoefening
Resultaat:

React
Achtergrond



Waarom React?
-
Plain vanilla Javascript heeft een aantal nadelen
-
Veel manuele DOM-manipulatie
-
Moeilijk schaalbaar bij groeiende applicaties
-
Kans op fouten wanneer data en UI niet in sync zijn
-
...
-
Dit hebben we net (kleinschalig) ervaren in de likes-oefening.
-
Plain vanilla Javascript heeft een aantal nadelen
-
Veel manuele DOM-manipulatie
-
Moeilijk schaalbaar bij groeiende applicaties
-
Kans op fouten wanneer data en UI niet in sync zijn
-
...
-

Waarom React?
Imperatief programmeren
Beschrijven hoe iets moet gebeuren.
element.innerText = text;
element.classList.add("active");-
Jij beslist wanneer en hoe de UI verandert
-
Meer controle, maar ook meer verantwoordelijkheid

Waarom React?
Declaratief programmeren
Beschrijven wat het eindresultaat moet zijn
<p className="active">{text}</p>-
React regelt de updates
-
Minder kans op fouten
-
Code is makkelijker te begrijpen

Waarom React?
Waarom werkt plain JavaScript niet goed op schaal?
-
Veel
getElementById/querySelector -
Meerdere
render()-functies -
Data wordt op meerdere plaatsen gebruikt
-
Kleine wijziging → veel code aanpassen
“Dit werkt voor kleine voorbeelden, maar niet voor echte apps.”

Waarom React?
Het antwoord: Component based frameworks
React, Angular, Vue, ... werken met componenten:
-
Kleine, herbruikbare stukken UI
-
Elk component heeft:
-
eigen structuur
-
eigen logica
-
eigen data
-
App
├── Likes
├── Button
└── Counter
Waarom React?
Voordelen van component based & declaratief werken
-
Leesbaar
-
Testbaar
-
Herbruikbaar
-
Onderhoudbaar
-
Makkelijk uitbreidbaar

Waarom React?
Waarom kiezen wij voor React?
-
Zeer populair in de industrie
-
Grote community
-
Veel jobs
-
Werkt samen met TypeScript
-
Enkel focussen op UI (library, geen framework)
React laat ons UI bouwen op een manier die leesbaar, voorspelbaar en schaalbaar is.
React
Start a project



Start a project
- We gebruiken een tool die alles voor ons klaarzet. (vite)
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
npm run dev
Start a project
- Vite zet voor ons bepaalde zaken klaar zoals:
-
Ontwikkelserver
-
Build configuratie
-
Moderne JavaScript setup
-
Live reload
-
Zonder deze tool zou dat veel werk zijn

Start a project
- Je krijgt heel wat files maar de belangrijkste files zijn:
my-react-app/
├── node_modules/
├── public/
├── src/
│ ├── App.tsx
│ └── main.tsx
├── index.html
└── package.json
Start a project
De belangrijkste files voorlopig zijn main.tsx en App.tsx
├── src/
│ ├── App.tsx
│ └── main.tsx
main.tsx
-
Startpunt van de applicatie
-
Verbindt React met de HTML
-
Hier werken we bijna nooit
App.tsx
-
Hoofdcomponent van onze applicatie
-
Hier bouwen we onze UI
-
Dit is waar alles samenkomt.

Start a project
Hoe bouwen we een UI in react?
-
We maken components
-
Components zijn JavaScript-functies
-
Components geven JSX terug
-
Components kunnen data ontvangen (props)
Tip: Het bestand eindigt op TSX bij ons omdat wij typescript gebruiken. Zonder typescript is het javascript dus JSX
React
Likes oefening (React)



Likes oefening
We bouwen de Facebook likes opnieuw,
maar nu in React, zonder DOM-manipulatie.
➡️ Logica blijft hetzelfde.

Likes oefening
Plak de likes function uit opwarmoefening in App.tsx
function likes(names) {
if (names.length === 0) return "No one likes this";
if (names.length === 1) return `${names[0]} likes this`;
if (names.length === 2) return `${names[0]} and ${names[1]} like this`;
if (names.length === 3)
return `${names[0]}, ${names[1]} and ${names[2]} like this`;
return `${names[0]}, ${names[1]} and ${names.length - 2} others like this`;
}
Likes oefening
Nu pakken we de rendering aan van onze App.
function App() {
const names = [];
return (
<div className="card">
<div className="likes">
<span className="icon">❤️</span>
<span>{likes(names)}</span>
</div>
</div>
);
}
-
Geen
getElementById -
Geen
innerText -
Geen
render()

Likes oefening
text.innerText = likes(names);
-
In React beschrijven we wat er moet staan
-
React zorgt voor de DOM
Vanilla javascript
React
<span>{likes(names)}</span>
Likes oefening
<span class="icon">❤️</span>
-
JSX: syntax om HTML en Javascript te combineren
-
Indien TypeScript → TSX
-
-
Kan niet om met gereserveerde woorden in JS/TS
bv. class (→ className), for (→ htmlFor), ...
Vanilla javascript
React
<span className="icon">❤️</span>
Likes oefening
-
Waarom niet?
-
Wat missen we?
We zien nu wel onze UI maar niets is interactief.

Likes oefening
Wat React nu al voor ons oplost:
-
Geen DOM-manipulatie
-
Duidelijke link tussen data en UI
-
Leesbare code
-
Minder kans op fouten
Wat nog niet?
-
Dynamische data
-
Interactie

Conventies
-
Naam van de component:
start met een hoofdletter (App, Button ...) -
Componenten exporteer je als een functie
-
export default function App() { ... }
-
- In de curly braces ({}) kan je JavaScript schrijven
React
JSX



JSX
Goed om weten:
- JSX wordt door React omgevormd naar JavaScript tijdens het builden van je applicatie
- Error? Bekijk de output van je terminal-applicatie.

The rules of JSX
3 regels voor het gebruik van JSX:
- Geef altijd maximaal 1 HTML-element terug of
gebruik een fragment (<>) - Sluit alle tags
- Gebruik (bijna) overal camelCase
React
useState



useState
function App() {
let names = [];
function addLike() {
names.push("Peter");
}
return (
<div>
<button onClick={addLike}>Add like</button>
<p>{likes(names)}</p>
</div>
);
}Wat verwachten we? Wat gebeurt er?
We maken nu een addLike functie en plaatsen deze op de button in App.tsx

useState
React rendert componenten opnieuw bij verandering.
Variabelen worden dan opnieuw aangemaakt.
Wat is hier het probleem?
- Gewone variabele in React
-
React onthoudt ze niet
-
Ze verdwijnen bij elke render
-
React weet niet dat ze veranderd zijn
-

useState
➡️ Dat is precies wat useState doet.
We hebben een manier nodig om:
-
data te onthouden tussen renders
-
React te verwittigen dat data werd gewijzigd

useState
useState is een React Hook die data bewaart
én React laat weten wanneer die data verandert.
Wat is een useState?

useState
import { useState } from "react";
function App() {
const [names, setNames] = useState([]);
return (
<div>
<p>{likes(names)}</p>
</div>
);
}-
names→ huidige waarde -
setNames→ enige manier om te wijzigen -
useState([])→ startwaarde

useState
Aanpassen van een state
function addLike() {
setNames([...names, "Peter"]);
}-
Geen
push -
Nieuwe array maken
-
React ziet het verschil → re-render

useState
| Gewone variabele | useState |
|---|---|
| Wordt vergeten | Blijft bestaan |
| Triggert geen render | Triggert render |
| React weet niets | React weet alles |
Waarom gebruiken we niet altijd een useState?

Try it yourself!
Oefening 1: Number state tonen
Maak een useState count met startwaarde 0
Toon de waarde in de UI.

Try it yourself!
Oefening 1: Number state tonen
-
Maak een state variabele
countmet startwaarde0 -
Toon de waarde van
count -
Verhoog
countmet 1 wanneer je op de knop klikt
import { useState } from "react";
function App() {
// TODO: maak een state variabele "count" met startwaarde 0
return (
<div>
{/* TODO: toon de waarde van count */}
<p>Count:</p>
{/* TODO: verhoog count met 1 bij klik */}
<button onClick={() => {}}>
Increment
</button>
</div>
);
}
export default App;
Try it yourself!
Oefening 2: Change Name
-
Maak een useState
namemet startwaarde "Peter" -
Toon “Hello {name}”
-
Verander naar "Sarah" wanneer je op de knop klikt
function App() {
// TODO: maak een state variabele "name" met startwaarde "Peter"
return (
<div>
{/* TODO: toon de naam in de tekst */}
<p>Hello</p>
{/* TODO: verander de naam naar "Sarah" bij klik */}
<button onClick={() => {}}>
Change name
</button>
</div>
);
}
export default App;
Try it yourself!
Oefening 3: Bool-Online
-
Maak een state
isOnlinemet startwaardetrue -
Toon "Online" of "Offline"
-
Toggle de waarde bij klik
function App() {
// TODO: maak een boolean state "isOnline" met startwaarde true
return (
<div>
<p>
Status:
{/* TODO: toon "Online" of "Offline" */}
</p>
{/* TODO: toggle isOnline bij klik */}
<button onClick={() => {}}>
Toggle status
</button>
</div>
);
}
export default App;React
Components (refactoring)



Component
Waarom splitsen we code op?
-
Veel JSX in één bestand
-
Moeilijk leesbaar
-
Moeilijk herbruikbaar
-
Alles hangt samen

Component
React component is:
-
Een JavaScript functie
-
Die JSX teruggeeft
-
En een stuk UI beschrijft
function MyComponent() {
return <div>Hello</div>;
}
Component
In onze huidige app hebben we dit:
function App() {
const [names, setNames] = useState([]);
return (
<div className="card">
<button onClick={() => setNames([...names, "Peter"])}>
Add like
</button>
<div className="likes">
<span>❤️</span>
<span>{likes(names)}</span>
</div>
</div>
);
}Zien jullie hier verschillende 'stukken' UI in?

Component
De UI bestaat uit:
-
Likes weergave
-
Actie (knop)
Card
├── Button
└── LikesZien jullie hier verschillende 'stukken' UI in?

Component
Zo kunnen we een eerste component "Likes" maken.
Dit doen we vaak in een mapje "components".
function Likes({ names }) {
return (
<div className="likes">
<span>❤️</span>
<span>{likes(names)}</span>
</div>
);
}-
nameskomt van buitenaf (Prop) -
Component is stateless
-
Logica blijft herbruikbaar
components/Likes.tsx

Component
Deze component kunnen we makkelijk gebruiken in App.
import Likes from "./components/Likes";
function App() {
const [names, setNames] = useState([]);
return (
<div className="card">
<button onClick={() => setNames([...names, "Peter"])}>
Add like
</button>
<Likes names={names} />
</div>
);
}We hebben code opgesplitst zonder functionaliteit te verliezen

Props
Props = Data voor een component
-
Vergelijkbaar met functie-argumenten
-
Alleen-lezen
-
Van parent → child
<Likes names={names} />Herbruikbaar met andere data!
<Likes names={names} />
<Likes names={["Peter"]} />
<Likes names={["Anna", "Lisa"]} />
Props
Wat hoort waar?
-
State → zo hoog mogelijk
-
UI → zo laag mogelijk
-
Logica → bij de component die ze gebruikt
Voordelen van components:
-
Leesbaardere code
-
Herbruikbare UI
-
Makkelijker testen
-
Makkelijker uitbreiden

Try it yourself!
Oefening 1: Circle component
-
Maak een component
Circle -
De component toont een gekleurde cirkel
-
Render de component in
App.tsx
function Circle() {
// TODO: return JSX die een cirkel toont
return (
);
}
Try it yourself!
Oefening 2: Badge component
-
Maak een component
Badge -
De component toont een label in een gekleurd vakje
-
Geef de tekst door via props
type BadgeProps = {
// TODO: voeg een prop "text" toe
};
function Badge(props: BadgeProps) {
return (
{/* TODO: toon de tekst */}
);
}
Try it yourself!
Oefening 3: ProfileCard component
-
Maak een component
ProfileCard -
Toon een naam en leeftijd
-
Geef beide waarden door via props
Geen Startercode?!
Probeer nu zelf code te schrijven zonder start
Try it yourself!
Oefening 4: StatusMessage component
-
Maak een component
StatusMessage -
Toon “Online” of “Offline”
-
Geef de status door via een boolean prop
React
Events



Interactie met components
Tot nu toe:
-
Data ging van parent → child
-
Maar UI bevat vaak knoppen en acties
Hoe laten we een component iets “doen”?

Events
Events in React:
-
React gebruikt camelCase
-
Events krijgen een functie
<button onClick={handleClick}>Click me</button>Wat is anders met vanilla JS?
- Geen strings
- Geen getElement
- Geen
addEventListener

Events
We maken het voorbeeld met de LikeButton
function LikeButton() {
return <button>Add like</button>;
}Probleem:
-
Deze knop weet niets over
names -
Waar komt de logica?

Events
Oplossing: Functie doorgeven als prop
function LikeButton({ onLike }) {
return <button onClick={onLike}>Add like</button>;
}Component voert gedrag uit dat het krijgt.
Wij zullen vanuit App de functie meegeven aan de LikeButton die de veranderingen teweeg zullen brengen.

Events
De state blijft in onze App en we maken een functie aan om door te geven aan de LikeButton
function App() {
const [names, setNames] = useState([]);
function addLike() {
setNames([...names, "Peter"]);
}
return (
<div className="card">
<LikeButton onLike={addLike} />
<Likes names={names} />
</div>
);
}
-
State blijft bovenaan
-
Child triggert verandering

Events
Data flow in React
App (state)
↓ props
LikeButton Likes
↑ events ↑ props
- Data gaat naar beneden
- Events gaan naar boven
React
useEffect



useEffect
Tot nu toe:
-
We beschrijven UI
-
UI volgt uit state
-
Components zijn puur
Maar… wat als we iets willen doen naast renderen?

useEffect
Dit noement we een side effect.
Side effects zijn dingen die:
-
Niet puur UI zijn
-
Buiten React gebeuren
Voorbeelden:
-
console.log -
document.title -
API calls (later)
-
timers

useEffect
Hiervoor maken we gebruiken van een andere hook genaamd useEffect.
useEffect laat je code uitvoeren na het renderen van een component.
useEffect(() => {
console.log("Rendered");
});
useEffect
Voorbeeld:
import { useEffect } from "react";
function App() {
useEffect(() => {
console.log("App rendered");
});
return <h1>Hello</h1>;
}-
Wordt uitgevoerd na render
-
Kan meerdere keren lopen

useEffect
Dependencies zijn zaken die je kan meegeven aan de useEffect waarop die moet letten. (Array na de function)
useEffect(() => {
console.log("Names changed");
}, [names]);-
Effect loopt wanneer
namesverandert -
React vergelijkt oude en nieuwe waarde
TIP: Wil je dat het maar 1 keer gebeurd? Geef dan een lege dependency array mee.

useEffect
Waar kunnen we dit gebruiken? Als we dit op onze likes oefening toepassen kan dit als volgt:
useEffect(() => {
document.title = `${names.length} likes`;
}, [names]);Nu zal de titel van het document aanpassen iedere keer als de array van names verandert.

useEffect
Wat is useEffect NIET?
-
vervanging van
useState -
render functie
-
event handler
➡️ useEffect = reactie op verandering

useEffect
Wanneer gebruiken we useEffect?
-
Je iets moet doen na render
-
Iets buiten React moet gebeuren
Gebruik het niet voor:
-
berekeningen
-
UI-logica

Try it yourself
Oefening 1:
-
Gebruik
useEffect -
Log
"Component rendered"in de console -
Laat het effect lopen na elke render
import { useEffect } from "react";
function App() {
// TODO: voeg een useEffect toe die iets logt in de console
return (
<div>
<h1>Hello React</h1>
</div>
);
}
export default App;
Try it yourself
Oefening 2:
-
Maak een state
count -
Verhoog
countbij klik -
Gebruik
useEffecten log wanneercountverandert
function App() {
// TODO: maak een state "count" met startwaarde 0
// TODO: gebruik useEffect om iets te loggen wanneer count verandert
return (
<div>
{/* TODO: toon count */}
<p>Count:</p>
{/* TODO: verhoog count bij klik */}
<button onClick={() => {}}>
Increment
</button>
</div>
);
}
export default App;
Try it yourself
Oefening 3:
-
Maak een state
likes -
Gebruik
useEffectom de pagina-titel aan te passen
function App() {
// TODO: maak een state "likes" met startwaarde 0
// TODO: gebruik useEffect om document.title aan te passen
// Tip: gebruik likes in de dependency array
return (
<div>
{/* TODO: toon likes */}
<p>Likes:</p>
{/* TODO: verhoog likes bij klik */}
<button onClick={() => {}}>
Add like
</button>
</div>
);
}
export default App;React
Oefeningen



Oefeningen
Oefening 1 - Emoji Counter
-
Maak een component
EmojiCounterdie een emoji en een teller toont -
Klikken op de knop verhoogt de teller
-
Log in
useEffecttelkens als de teller verandert

Oefeningen
Oefening 2 - Tamagochi
-
Component
PetCardmet propsname -
Houd interne states bij:
hungerenhappiness -
Knoppen: “Feed” en “Play”
-
useEffect logt als
hunger > 5(“Pet is hungry!”)

Oefeningen
Oefening 3 - Countdown Timer
-
Component
TimerDisplaytoonttimeLeft -
In App: start timer bij klik, tel af van 10 naar 0
-
useEffect zorgt dat timer telt

Oefeningen
Oefening 4 - Mood Tracker
-
Component
Moodmet propemoji -
In App: state
currentMoodmet startwaarde"😊" -
Knoppen in App:
"😊"en"😢"→ verandert state -
useEffect logt
"Mood changed: {currentMood}"

Oefeningen
Oefening 5 - Click Me Counter
-
Component
ClickDisplaymet propcount→ toont"Clicked {count} times" -
In App: state
clickCountstart op 0 -
Knop “Click me” → verhoogt
clickCount -
useEffect logt
"Clicked: {clickCount}"
PGM3/2 - React Basics
By Lecturer GDM
PGM3/2 - React Basics
- 35