aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Webontwikkeling

React useState: de basis van state-beheer

react usestate is de meest elementaire manier om veranderende data (state) op te slaan binnen een functiecomponent. Een teller, een formulierveld, of een dropdown open of dicht is… alles wat verandert door gebruikersinteractie is state, en je moet het met useState bewaren zodat React de verandering op het scherm kan tonen. Een gewone variabele bijwerken triggert React niet; useState daarentegen slaat de waarde op én re-rendert het component wanneer die verandert.

Hoe useState werkt

useState krijgt een beginwaarde en geeft een array van twee elementen terug: de huidige waarde en de functie die deze wijzigt. We benoemen beide tegelijk met array-destructuring:

import { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount(count + 1)}>
      Geklikt: {count}
    </button>
  );
}

Hier is count de huidige waarde en setCount de functie die deze wijzigt. De 0 in useState(0) wordt alleen bij de eerste render gebruikt; bij latere renders onthoudt React de vorige waarde. De naamgeving is helemaal aan jou, maar de conventie [x, setX] is standaard.

Muteer state nooit direct

De meest gemaakte fout in React is het direct muteren van state. De enige manier om state te wijzigen is de set-functie aanroepen. Direct toewijzen, zoals hieronder, werkt het scherm niet bij:

// FOUT — React merkt dit niet op
count = count + 1;

// GOED — triggert een re-render
setCount(count + 1);

Dezelfde regel geldt voor objecten en arrays. In plaats van het bestaande object te wijzigen, maak je een nieuw object. De reden: React detecteert wijzigingen via referentievergelijking (is de oude waarde dezelfde als de nieuwe); als je dezelfde referentie muteert, beseft React niet dat er iets is veranderd.

const [user, setUser] = useState({ naam: "Ada", leeftijd: 30 });

// FOUT
user.leeftijd = 31;
setUser(user);

// GOED — een nieuw object via spread
setUser({ ...user, leeftijd: 31 });

Functionele updates: waarom en wanneer?

In plaats van een waarde rechtstreeks aan de set-functie te geven, kun je ook een functie meegeven die de vorige state als argument ontvangt. Dit heet een functionele update, en het is de veiligste methode wanneer de nieuwe waarde afhangt van de oude:

// hangt af van de vorige waarde: gebruik bij voorkeur de functionele vorm
setCount(prev => prev + 1);

Het verschil komt naar voren wanneer je de state meerdere keren bijwerkt binnen dezelfde gebeurtenis. Vergelijk deze twee voorbeelden:

// Dit verhoogt de teller met slechts 1
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);

// Dit verhoogt de teller met 3
setCount(prev => prev + 1);
setCount(prev => prev + 1);
setCount(prev => prev + 1);

In het eerste blok is count de vaste waarde van die render (bijvoorbeeld 0), dus alle drie de aanroepen berekenen 0 + 1. In de functionele vorm krijgt elke aanroep het resultaat van de vorige update, waardoor het resultaat correct optelt.

Batching van updates

React groepeert meerdere state-updates binnen dezelfde event-handler in één render; dit heet batching. Dus zelfs als je drie afzonderlijke set-aanroepen doet, re-rendert het component één keer en niet drie keer. Dit verbetert de prestaties en voorkomt dat half afgemaakte tussentoestanden op het scherm verschijnen.

function handleClick() {
  setOpen(true);
  setTeller(t => t + 1);
  setBericht("bijgewerkt");
  // alle drie worden in één render toegepast
}

Met React 18 geldt dit gedrag niet alleen voor event-handlers, maar ook voor setTimeout, Promises en andere asynchrone callbacks (automatische batching). Een belangrijk punt: direct na het aanroepen van de set-functie bevat de state-variabele nog de oude waarde, omdat de update pas bij de volgende render van kracht wordt.

setCount(count + 1);
console.log(count); // nog steeds de oude waarde — de render is nog niet gebeurd

Praktische patronen met arrays en objecten

De regel is hetzelfde bij complexe state: kopiëren, wijzigen, setten. Veelgebruikte patronen:

  • Een item aan een lijst toevoegen: setItems(prev => [...prev, nieuw])
  • Uit een lijst verwijderen: setItems(prev => prev.filter(i => i.id !== id))
  • Eén item bijwerken: setItems(prev => prev.map(i => i.id === id ? { ...i, done: true } : i))

Als je state sterk vertakt en veel onderling afhankelijke velden bevat, kan useReducer leesbaarder zijn dan useState. Maar voor het meeste dagelijkse werk volstaat useState en is het de eenvoudigste oplossing.

Veelgestelde vragen

Wat is het verschil tussen useState en useRef?

useState re-rendert het component wanneer het verandert; het is bedoeld voor data die op het scherm moet verschijnen. useRef bewaart een waarde tussen renders maar triggert geen render wanneer die verandert; het wordt gebruikt om een DOM-element te benaderen of om een waarde vast te houden die de rendering niet beïnvloedt.

Mag ik useState in een lus of voorwaarde aanroepen?

Nee. Alle Hooks moeten op het hoogste niveau van het component worden aangeroepen, in dezelfde volgorde bij elke render. Ze voorwaardelijk of in een lus aanroepen breekt het vermogen van React om states te koppelen en geeft een fout.

Wat als de beginwaarde een dure berekening is?

Geef in plaats van de beginwaarde direct mee te geven een functie mee: useState(() => dureBerekening()). Deze "lazy initializer" draait alleen bij de eerste render en wordt bij latere renders niet opnieuw berekend.

State-beheer goed opzetten is de basis van een onderhoudbare interface. Bouw je een React-project of wil je een bestaande interface verbeteren? Neem contact met me op — laten we samen een solide architectuur bouwen.

Bu kategorideki tüm yazılar →

Devamı için