Waarom heb je useEffect nodig?

Stel je wilt iets doen zodra je component wordt geladen. Je zou denken: "Ik schrijf gewoon code in mijn component!"

Dit gaat fout (infinite loop!):

const Counter = () => {
  const [count, setCount] = useState(0);
  
  // Dit zorgt voor een infinite loop!
  setCount(count + 1);
  
  return <div>Count: {count}</div>;
};

Probleem: Elke keer dat je setCount aanroept, rendert het component opnieuw. Bij elke render wordt setCount weer aangeroepen → infinite loop!

Wat is useEffect?

useEffect is een React Hook die ervoor zorgt dat code wordt uitgevoerd op het juiste moment - niet bij elke render.

Wanneer gebruik je useEffect?

  • Data ophalen van een API zodra component laadt
  • De pagina titel veranderen
  • Een timer starten
  • Iets in de console loggen bij het laden

useEffect importeren

import { useState, useEffect } from "react";

Basis Syntax

useEffect(() => {
  // Code die je wilt uitvoeren
  console.log('Component is geladen!');
}, []); // ← Dependency array

useEffect heeft 2 dingen:

  1. Een functie - de code die je wilt uitvoeren
  2. Een dependency array - wanneer de code moet worden uitgevoerd

Dependency Array

De dependency array [] bepaalt wanneer useEffect wordt uitgevoerd:

1. Lege Array [] - Eén keer bij laden

useEffect(() => {
  console.log('Component geladen!');
}, []); // Voer 1x uit bij mount

Gebruik dit voor: Data fetchen, timers starten, document title aanpassen

2. Met Dependencies - Bij verandering

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

useEffect(() => {
  console.log('Count veranderde naar:', count);
}, [count]); // Voer uit elke keer als count verandert

3. Geen Array - Bij elke render

useEffect(() => {
  console.log('Component renderde opnieuw');
}); // Voer uit bij elke render (meestal niet nodig!)

Let op: Zonder dependency array wordt useEffect bij elke render uitgevoerd. Dit wil je bijna nooit!

Praktische Voorbeelden

Document Title Aanpassen

import { useState, useEffect } from 'react';

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

  useEffect(() => {
    document.title = `Count: ${count}`;
  }, [count]); // Update title als count verandert

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

Console Log bij Laden

useEffect(() => {
  console.log('Component is gemount!');
}, []); // Voer 1x uit bij laden

Data Fetchen (basis)

import { useState, useEffect } from 'react';

const Users = () => {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    // Fetch data bij laden
    fetch('https://api.example.com/users')
      .then(res => res.json())
      .then(data => setUsers(data));
  }, []); // Lege array = 1x uitvoeren

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
};

Cleanup Function

Soms moet je opruimen (cleanup) als component unmount. Bijvoorbeeld bij timers of event listeners:

Timer Voorbeeld

import { useState, useEffect } from 'react';

const Timer = () => {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    // Start timer
    const interval = setInterval(() => {
      setSeconds(s => s + 1);
    }, 1000);

    // Cleanup: stop timer bij unmount
    return () => {
      clearInterval(interval);
    };
  }, []); // Lege array = 1x uitvoeren

  return <div>Seconds: {seconds}</div>;
};

Cleanup function:

De functie die je return in useEffect wordt uitgevoerd als het component unmount. Gebruik dit om timers te stoppen, event listeners te verwijderen, etc.

Belangrijke Regels

  • Altijd dependency array gebruiken - Anders elke render!
  • Lege array [] voor "run once" - Bij component mount
  • Dependencies toevoegen - Als je state/props gebruikt in useEffect
  • Cleanup bij timers/listeners - Return functie voor cleanup

Veelgemaakte Fouten

Fout - Geen dependency array:

useEffect(() => {
  setCount(count + 1);  // Infinite loop!
}); // Geen array = elke render!

Goed - Met lege array:

useEffect(() => {
  // Voer 1x uit
}, []); // Lege array = mount only

Fout - Missing dependency:

useEffect(() => {
  console.log(count);
}, []); // count ontbreekt in array!

Goed - Dependency toegevoegd:

useEffect(() => {
  console.log(count);
}, [count]); // count is toegevoegd

Fout - Timer niet opruimen:

useEffect(() => {
  setInterval(() => {
    console.log('tick');
  }, 1000);
  // Geen cleanup = memory leak!
}, []);

Goed - Met cleanup:

useEffect(() => {
  const id = setInterval(() => {
    console.log('tick');
  }, 1000);
  
  return () => clearInterval(id); // Cleanup!
}, []);