React Hooks hebben een revolutie teweeggebracht in de manier waarop we function components in React schrijven, en bieden een beknopte en krachtige manier om state en side effects te beheren.

Maar zoals met elke nieuwe functie, komt het met zijn eigen set regels en richtlijnen. Een veel voorkomende fout die React developers kunnen tegenkomen is de “React hooks must be called in a React function component or a custom React hook function” fout.

In dit artikel duiken we in de details van deze fout, begrijpen we waarom hij optreedt, en geven we best practices om hem op te lossen.

De oorzaak van de “React hooks must be called in a React function component or a custom React hook function” fout

Er zijn regels verbonden aan het gebruik van React hooks. Toch zijn er veel React developers die het hier niet zo nauw mee nemen bij het leren van React, wat leidt tot fouten. Een van deze fouten is “React hooks must be called in a React function component or a custom React hook function”.

Deze fout treedt op doordat er twee belangrijke dingen gebeuren:

  • React Hooks gebruiken in class components
  • Het callen van React hooks binnen een nested functie

React hooks, zoals useState, useEffect, en useContext, zijn ontworpen om gecalld te worden op het hoogste niveau van een function component of een custom hook functie. Ze mogen ook alleen worden gecalld in function components en niet in class components. Dit zijn twee belangrijke regels rond React hooks, die ervoor zorgen dat hooks correct en consistent worden gebruikt in React components.

Als Hooks op ongeldige plaatsen worden gecalld, krijg je deze foutmelding: “React hooks must be called in a React function component or a custom React hook function”. Deze ESLint fout is als een beveiliging om te voorkomen dat hooks worden gebruikt op manieren die onverwacht gedrag en bugs in je React applicatie kunnen veroorzaken.

2 manieren om de “React hooks must be called in a React function component or a custom React hook function” fout op te lossen

Deze fout kan op een paar manieren worden opgelost, afhankelijk van de situatie of hoe je de React hook verkeerd hebt gebruikt.

1. Call React hooks nooit in class compoments

Hooks zijn ontworpen om alleen te werken met function components of custom hooks – omdat ze de call stack van de function components gebruiken om de state en levenscyclus van de component te beheren. Class components hebben deze call stack niet, dus je kunt hooks er niet rechtstreeks in gebruiken.

import React, { useState } from 'react';
class Counter extends React.Component {
    state = { count: 0 };
    render() {
        const [count, setCount] = useState(0);
        // Error: React Hooks must be called in a React function component or a custom React Hook function
        return (
            <div>
                <p>You clicked {count} times</p>
                <button onClick={() => setCount(count + 1)}>Click me</button>
            </div>
        );
    }
}
export default Counter;

Doe je dat wel, dan krijg je deze foutmelding:

React function error
Fout

Er zijn echter een paar manieren om dit op te lossen, afhankelijk van je voorkeur. Je kunt besluiten state en setState te gebruiken met class components, de component omzetten in een function component, of een Higher-Order Component (HOC) gebruiken.

A. Zet de class component om in een function component

De enige manier waarop hooks kunnen werken is wanneer je een function component gebruikt. Dit komt omdat hooks ontworpen zijn om te werken met function components.

In het onderstaande voorbeeld wordt de vorige class component omgezet in een function component:

import { useState } from 'react';

function MyComponent(props) {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

B. Gebruik een Higher-Order Component (HOC)

Een manier om hooks te gebruiken in een class component is het gebruik van een Higher-Order Component (HOC).

HOC is een functie die een component neemt en een nieuwe component teruggeeft met extra props of functionaliteit. Hier is een voorbeeld van hoe je een HOC kunt gebruiken om hooks aan een class component te geven:

import React, { useState } from 'react';

function withHooks(WrappedComponent) {
  return function(props) {
    const [count, setCount] = useState(0);
    return (
      < WrappedComponent count={count} setCount={setCount} {...props} />
    );
  };
}

class MyComponent extends React.Component {
  render() {
    const { count, setCount } = this.props;
    return (
      < div>
        < p>Count: {count}< /p>
        < button onClick={() => setCount(count + 1)}>Increment< /button>
      < /div>
    );
  }
}

export default withHooks(MyComponent);

C. Gebruik state  in een class component

Stel dat je de syntaxis van je component niet wilt veranderen. Dan zou je kunnen besluiten om  state en setState te gebruiken in plaats van de useState hook:

import React from 'react';

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  handleIncrement = () => {
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.handleIncrement}>Increment</button>
      </div>
    );
  }
}

export default MyComponent;

2. Call React hooks nooit binnen een nested functie

Een duidelijke regel van React Hooks is dat alle hooks moeten worden gecalld op het hoogste niveau van een function component of een custom hook functie. Als je een hook dus callt binnen een nested functie, heb je deze regel overtreden.

In het onderstaande voorbeeld wordt de useState Hook gecalld in de handleClick functie:

import React, { useState } from 'react';
function MyComponent() {
    let count = 0;
    function handleClick() {
        const [count, setCount] = useState(0);
        setCount(count + 1);
    }
    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={handleClick}>Increment</button>
        </div>
    );
}

export default MyComponent;

Dit gooit de volgende fout:

Nog een React error
Voorbeeld fout

Je kunt dit oplossen door de hook buiten de functie te verplaatsen – naar het hoogste niveau van je function component:

import React, { useState } from 'react';

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

    function handleClick() {
        setCount(count + 1);
    }

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={handleClick}>Increment</button>
        </div>
    );
}

export default MyComponent;

Samenvatting

In dit artikel heb je geleerd wat de oorzaak is van de fout “React hooks must be called in a React function component or a custom React hook function”, en hoe die kan worden opgelost.

Volg altijd de regels van React hooks bij het werken en gebruiken ervan in je React projecten om te voorkomen dat je fouten als deze ervaart.

Op zoek naar de ideale hostingoplossing voor je React applicaties? Test Kinsta’s Applicatie Hosting gratis uit!

We horen graag van je! Heb je deze fout ooit eerder meegemaakt? Zo ja, hoe heb je het opgelost? Heb je een andere aanpak gebruikt die niet in dit artikel is behandeld? Deel je gedachten in de comments hieronder!