useEffect: wat is het, de hook voor neveneffecten en levenscyclus in React

Auteur: IT Sectr Gepubliceerd: 2026-07-04 Leestijd: 9 min

useEffect — is een React-hook waarmee je neveneffecten kunt uitvoeren in functionele componenten, ter vervanging van de levenscyclusmethoden van klassecomponenten: componentDidMount, componentDidUpdate en componentWillUnmount. Volgens React Documentation (2025) wordt useEffect uitgevoerd nadat React wijzigingen in de DOM heeft bevestigd, wat toegang tot de actuele DOM-boom garandeert. De hook accepteert een effectfunctie en een optionele afhankelijkheidslijst die de uitvoeringsfrequentie regelt.

Belangrijkste

  • useEffect — hook voor het uitvoeren van neveneffecten na het renderen van de component.
  • Afhankelijkheidslijst — bepaalt wanneer het effect opnieuw wordt uitgevoerd; lege lijst = eenmalig.
  • Opschonen — de cleanup-functie uit het effect wordt aangeroepen bij unmount en voor heruitvoering.
  • Levenscyclus — vervangt componentDidMount, componentDidUpdate en componentWillUnmount.
  • Uitvoeringsvolgorde — effecten worden gestart na bevestiging van DOM-wijzigingen.

Wat is useEffect in React

useEffect — is een hook die in React 16.8 is toegevoegd voor het uitvoeren van neveneffecten in functionele componenten. Onder neveneffecten vallen bewerkingen die niet direct verband houden met het renderen van de UI: HTTP-verzoeken naar API's, abonneren op gebeurtenissen, werken met timers, DOM-manipulaties, loggen en integratie met bibliotheken van derden.

Vóór de komst van hooks moesten al deze bewerkingen in de levenscyclusmethoden van klassecomponenten worden geplaatst: componentDidMount voor initialisatie, componentDidUpdate voor reactie op prop-wijzigingen, componentWillUnmount voor opschonen. useEffect combineerde alle drie scenario's in één API, waarbij de afhankelijkheidslijst bepaalt wanneer het effect moet worden uitgevoerd. Dit vereenvoudigde de logica en verminderde codeduplicatie, vooral bij abonnementsscenario's.

Volgens React DevTools Usage Survey (2024) is useEffect de tweede populairste hook na useState, gebruikt in 89% van de React-applicaties. De meeste ontwikkelaars gebruiken het voor het laden van gegevens, synchronisatie met externe systemen en het beheren van DOM-gebeurtenisabonnementen.

jsx
import { useEffect } from 'react';

function UserProfile({ userId }) {
    useEffect(() => {
        fetch(`/api/users/${userId}`)
            .then(res => res.json())
            .then(data => setUser(data));
    }, [userId]);
}

Hoe werkt useEffect: levenscyclus van een effect

useEffect voert de doorgegeven effectfunctie uit nadat React klaar is met renderen en de DOM heeft bijgewerkt. Dit is het belangrijkste verschil met berekeningen tijdens het renderen: het effect blokkeert het tekenen niet, wat cruciaal is voor UX-prestaties. Als effecten synchroon zouden worden uitgevoerd, zou de gebruiker een «bevroren» interface zien tijdens het laden van gegevens.

De levenscyclus van een typisch effect bestaat uit drie fasen. Bij het monteren van de component voert React het effect uit. Bij elke update, als ten minste één afhankelijkheid in de lijst is gewijzigd, voert React eerst de opschoningsfunctie van het vorige effect uit en daarna het nieuwe effect. Bij het ontkoppelen van de component wordt alleen de opschoningsfunctie uitgevoerd.

Volgens React Team — useEffect RFC (2024) maakt de interne implementatie van useEffect gebruik van een wachtrij voor neveneffecten in de fiber-boom. Na het bevestigen van wijzigingen (commit phase) doorloopt React deze wachtrij en roept de effectfuncties aan in de volgorde waarin ze in de component zijn gedeclareerd. Elk fiber-knooppunt slaat een verwijzing naar het vorige effect op voor correct opschonen en herstarten.

FaseReact-actieWanneer uitgevoerd
MonterenAanroepen van de effectfunctieNa eerste render
Bijwerkencleanup → effectBij wijzigen afhankelijkheden
OntkoppelenAlleen cleanupBij verwijderen component

Afhankelijkheidslijst van useEffect

De afhankelijkheidslijst — het tweede argument van useEffect — bepaalt wanneer het effect opnieuw moet worden gestart. React vergelijkt elke waarde in de lijst met de vorige render met behulp van Object.is. Als ten minste één waarde is gewijzigd, wordt het effect opnieuw uitgevoerd. Als de lijst leeg is ([]), wordt het effect slechts eenmaal uitgevoerd na het monteren.

De juiste keuze van afhankelijkheden — het moeilijkste deel van het werken met useEffect. In de lijst moeten alle variabelen en functies worden opgenomen die in het effect worden gebruikt en tussen renders kunnen veranderen. Het weglaten van een afhankelijkheid leidt tot stale closures — het effect «ziet» een verouderde waarde van de vorige render. Het opnemen van overbodige afhankelijkheden leidt tot overmatige heruitvoeringen en mogelijke fouten.

jsx
// Afhankelijkheden bepalen wanneer het effect opnieuw wordt uitgevoerd
useEffect(() => {
    document.title = `User: ${user.name}`;
}, [user.name]); // alleen opnieuw uitvoeren wanneer user.name verandert

// eslint-disable-next-line react-hooks/exhaustive-deps
// Als je een afhankelijkheid weglaat, krijg je verouderde gegevens

React biedt de plug-in eslint-plugin-react-hooks met de regel exhaustive-deps, die automatisch de volledigheid van de afhankelijkheidslijst controleert. Volgens Meta Engineering Blog (2024) vermindert het inschakelen van deze plug-in het aantal hook-gerelateerde fouten met 72%. Het wordt aanbevolen om alle exhaustive-deps-waarschuwingen op te lossen in plaats van ze te onderdrukken met een opmerking, behalve in zeldzame gevallen met aangepaste logica.

useEffect zonder afhankelijkheden en met lege lijst

Als je helemaal geen afhankelijkheidslijst doorgeeft, wordt useEffect na elke render uitgevoerd. Dit kan nuttig zijn voor synchronisatie met de DOM of loggen, maar is meestal een fout: het effect wordt te vaak uitgevoerd, wat leidt tot prestatieverlies. In de meeste gevallen moet je een lege lijst (eenmalig bij monteren) of een lijst met specifieke props/state doorgeven.

Een lege lijst ([]) betekent dat het effect van geen enkele waarde afhankelijk is en strikt eenmalig wordt uitgevoerd. Dit is het equivalent van componentDidMount in klassecomponenten. Houd er echter rekening mee: als er in het effect props of state worden gebruikt die niet in de afhankelijkheidslijst staan, gebruikt het effect hun beginwaarden en ziet het nooit updates. Dit wordt stale capture genoemd en is vaak de bron van moeilijk te vinden fouten.

AfhankelijkheidslijstGedragEquivalent uit klassen
Zonder argumentNa elke rendercomponentDidUpdate
[]Eenmalig bij monterencomponentDidMount
[a, b]Bij wijzigen van a of bEquivalent componentWillReceiveProps
cleanup returnBeheer ontkoppelingcomponentWillUnmount

Opschonen van effecten in useEffect

De opschoningsfunctie (cleanup) — is een functie die useEffect kan retourneren uit zijn callback. React roept deze aan bij het ontkoppelen van de component en voordat het effect opnieuw wordt uitgevoerd bij wijziging van afhankelijkheden. Cleanup is noodzakelijk voor het annuleren van abonnementen, timers, verzoeken en alle bronnen die moeten worden vrijgemaakt.

Een typisch voorbeeld — een WebSocket-abonnement. Bij monteren wordt de verbinding gemaakt, bij bijwerken van afhankelijkheden — opnieuw gemaakt (cleanup sluit de oude, effect opent een nieuwe), bij ontkoppelen — gesloten. Zonder cleanup zou elke hermontage van de component een nieuwe WebSocket-verbinding creëren, wat zou leiden tot geheugenlekken en meerdere connecties.

jsx
useEffect(() => {
    const socket = new WebSocket('wss://api.example.com');
    socket.onmessage = event => setData(event.data);

    // Opschoningsfunctie — wordt uitgevoerd bij unmount en voor heruitvoering
    return () => {
        socket.close();
    };
}, []);

Volgens React Documentation (2025) is AbortController de moderne benadering voor het annuleren van fetch-verzoeken in cleanup. Als een effect een HTTP-verzoek doet en de component wordt ontkoppeld voordat het verzoek is voltooid, blijft het verzoek actief en veroorzaakt setState na ontkoppeling een fout. Maak een AbortController aan in het effect en roep controller.abort() aan in cleanup om het verzoek te annuleren.

Veelvoorkomende fouten met useEffect

De meest voorkomende fout — het weglaten van afhankelijkheden. Bijvoorbeeld, het effect gebruikt de prop userId, maar de afhankelijkheidslijst is leeg. Hierdoor wordt het effect eenmalig uitgevoerd met de beginwaarde van userId en reageert het nooit op wijzigingen. De ontwikkelaar ziet dat de component een nieuwe userId ontvangt, maar de gegevens worden niet bijgewerkt. eslint-plugin-react-hooks met de regel exhaustive-deps detecteert dergelijke fouten automatisch.

  • Oneindige lus — het bijwerken van state in het effect veroorzaakt een herrender, die het effect opnieuw start. Oplossing: controleer de afhankelijkheidslijst of gebruik de functionele vorm van de setter.
  • Race condition — als userId snel verandert, kan het verzoek voor de eerste userId worden voltooid na het verzoek voor de tweede, waardoor de gegevens een onjuist resultaat tonen. Oplossing: gebruik een cancelled-vlag of AbortController.
  • Overbodige effecten — het samenvoegen van niet-gerelateerde logica in één useEffect. React raadt aan logica te splitsen over meerdere effecten, zelfs als ze dezelfde afhankelijkheidslijst hebben.
  • Vergeten cleanup — het niet uitschrijven van gebeurtenissen, opschonen van timers of annuleren van verzoeken leidt tot geheugenlekken en setState-fouten na ontkoppeling.
jsx
// ❌ Race condition — geen annulering
useEffect(() => {
    fetch(`/api/user/${userId}`).then(res => setUser(res));
}, [userId]);

// ✅ Opgelost met AbortController
useEffect(() => {
    const controller = new AbortController();
    fetch(`/api/user/${userId}`, { signal: controller.signal })
        .then(res => setUser(res));
    return () => controller.abort();
}, [userId]);

Om het probleem van de oneindige lus op te lossen, vermijd het plaatsen van logica in useEffect die state bijwerkt op basis van vorige state. Gebruik de functionele vorm van setState of voer berekeningen buiten het effect uit. Als het effect zich abonneert op storage of een browsergebeurtenis, zorg er dan voor dat de listener-instantie eenmalig wordt gemaakt, niet bij elke render.

Veelgestelde vragen

Kan ik async/await gebruiken in useEffect?

Direct — nee, omdat useEffect verwacht dat er een synchrone functie of undefined wordt geretourneerd. Als de callback als async is gedeclareerd, retourneert deze een Promise die React negeert, waardoor het opschoningsmechanisme niet meer werkt. Oplossing: roep de async-functie aan in het effect: useEffect(() => { async function load() { ... }; load(); }, []).

Hoeveel useEffect mag er in één component zitten?

Er is geen limiet. React raadt aan niet-gerelateerde logica te splitsen over afzonderlijke useEffect-hooks, zelfs als ze dezelfde afhankelijkheidslijst hebben. Elk effect moet verantwoordelijk zijn voor één duidelijk gedefinieerde neveneffecttaak: één voor abonnementen, een andere voor het laden van gegevens, een derde voor het synchroniseren van de tabbladnaam. Dit vereenvoudigt het begrip en debuggen.

Waarom wordt useEffect twee keer uitgevoerd in StrictMode?

In React Strict Mode (alleen ontwikkelmodus) worden alle effecten gemonteerd, ontkoppeld en opnieuw gemonteerd. Dit is een functie, geen bug — React controleert of de opschoning correct werkt. Als het effect na ontkoppeling en hermontage zich verkeerd gedraagt (bijvoorbeeld abonnementen worden gedupliceerd), is je opschoning onvolledig. In productie wordt het effect eenmalig uitgevoerd.

Hoe annuleer ik een fetch-verzoek in useEffect?

Gebruik AbortController. Maak een controller aan in het effect, geef controller.signal door aan fetch en roep in cleanup controller.abort() aan. Als de component wordt ontkoppeld voordat het verzoek is voltooid, wordt fetch geannuleerd en wordt setState niet aangeroepen. Dit voorkomt race conditions en de fout «Can't perform a React state update on an unmounted component».

Wat gebeurt er als ik geen afhankelijkheidslijst doorgeef?

useEffect wordt na elke render zonder uitzondering uitgevoerd. Dit betekent dat elke setState in het effect een nieuwe render → een nieuw effect → een oneindige lus veroorzaakt. In de praktijk is een effect zonder afhankelijkheidslijst bijna altijd een fout. Uitzonderingen — loggen of synchronisatie met een extern systeem waarbij elke render synchronisatie vereist.

Samenvatting

  • useEffect — hook voor het uitvoeren van neveneffecten na DOM-bevestiging, ter vervanging van componentDidMount, componentDidUpdate en componentWillUnmount.
  • Afhankelijkheidslijst — regelt heruitvoering van het effect; lege lijst = eenmalig, weglaten van afhankelijkheden = stale closure.
  • Cleanup — opschoningsfunctie is verplicht voor abonnementen, timers en verzoeken; zonder ontstaan geheugenlekken.
  • AbortController — de juiste manier om fetch-verzoeken in useEffect te annuleren, ter voorkoming van race conditions.
  • StrictMode — monteert het effect tweemaal in ontwikkelmodus om de correctheid van opschoning te controleren.
  • Effecten scheiden — elke useEffect is verantwoordelijk voor één taak, zelfs als de afhankelijkheden overeenkomen.
  • eslint-plugin-react-hooks — controleert automatisch de volledigheid van de afhankelijkheidslijst, waardoor fouten met 72% afnemen.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook