Side-Effects

Soms willen we dat onze componenten iets doen dat niet binnen het takenpakket van een component hoort. Componenten moeten in principe alleen maar bezig zijn met het renderen van de UI. Maar Componenten moeten vaak wel bepaalde acties gaan uirvoeren die iets veroorzaken in de buitenwereld. Zo'n actie noemen we in React een side-effect. Een aantal voorbeelden van een side-effect kunnen zijn:

  • Het zetten van een title aan de hand van document.title

  • Het gebruiken van timers met setInterval en setTimeout

  • Het meten van de hoogte, breedte of positie van bepaalde elementen in de DOM

  • Het zetten of lezen van waarden uit de local storage

  • Data inlezen of schrijven naar externe web services.

Dit zijn allemaal dingen die we nooit rechtstreeks gaan doen in onze component code.

Als eerste voorbeeld van wanneer we side-effects moeten gebruiken gaan we eens zien naar het lezen en schrijven uit local storage. Local storage laat het toen bepaalde configuraties of user settings bij te houden in de browser van de gebruiker.

We gaan er nu voor zorgen dat alles wat er in het name veld wordt ingegeven wordt opgeslagen in de localstorage van de browser, zodat deze waarde volgende keer deze pagina wordt aangeroepen terug wordt getoond aan de gebruiker. We willen dus een bepaald stuk code laten lopen elke keer de name veranderd. Op het eerste gezicht zouden we het als volgt kunnen doen:

const handleNameChange: ChangeEventHandler<HTMLInputElement> = (event) => {
  setName(event.target.value);
  localStorage.setItem('name', name);
}

en kunnen we deze waarde uitlezen bij het zetten van de default waarde van onze state:

const [name, setName] = useState<string>(localStorage.getItem('name') ?? '');

Merk op dat we hier de ?? operator gebruiken van typescript. Dit maakt het mogelijk om een default waarde mee te geven als het deel voor de ?? undefined of null is.

Deze code zal op zich wel werken, maar er is 1 groot nadeel. We kunnen de functie handleNameChange nergens anders meer hergebruiken. Dus elke keer deze functie wordt aangeroepen zal de localstorage aangepast worden. We willen dit dus loskoppelen van elkaar. Hiervoor gebruiken we de useEffect hook om de side-effect te triggeren telkens de name state wordt aangepast:

  useEffect(() => {
    localStorage.setItem('name', name);
  },[name]);

De useEffect hook neemt twee argumenten aan: het eerste is een functie die de side-effect uitvoert. In dit geval is de side effect het opslaan van de name in de localStorage. Het tweede argument is een array van dependencies. Dit is een lijst van variabelen (of states of props) die wanneer ze veranderen de side-effect zullen triggeren. In ons geval zal dus elke keer name aangepast wordt, de localstorage waarde geüpdatet worden.

Twee belangrijke dingen die je zeker moet weten:

  • Als je de array argument weglaat dan zal de side-effect elke keer de component gerendered wordt opnieuw uitgevoerd worden.

  • Als je een lege array meegeeft dan zal de side-effect enkel getriggered worden als het component voor de eerste keer gerendered wordt. Dit kan handig zijn voor het inlezen van data van een API

Wil je bijvoorbeeld de title van de pagina updaten op het moment dat de component voor de eerste keer gerendered wordt kan je dit doen aan de hand van:

useEffect(() => {
  document.title = 'Games Store'
},[]);

Hoewel het lukt willen we nooit document.title aanpassen vanuit de code van het component zelf.

Last updated

Was this helpful?