O React Hooks revolucionou a maneira como escrevemos componentes funcionais no React, fornecendo uma maneira concisa e poderosa de gerenciar o estado e os efeitos colaterais.

No entanto, como acontece com qualquer novo recurso, ele vem com seu próprio conjunto de regras e diretrizes. Um erro comum que os desenvolvedores do React podem encontrar é o erro “react hooks must be called in a react function component or a custom react hook function”.

Neste artigo, iremos explorar os detalhes deste erro, entender por que ele ocorre e fornecer as melhores práticas para corrigi-lo.

Quais são as causas do erro “React Hooks Must Be Called In a React Function Component or a Custom React Hook Function”?

Existem regras envolvidas no uso de React Hooks. Muitos desenvolvedores do React ignoram essas regras ao aprender React, o que leva a erros. Um desses erros é “react hooks must be called in a react function component or a custom react hook function”.

Esse erro ocorre quando duas coisas importantes acontecem:

  • Usando React Hooks em componentes de classe
  • Chamando React Hooks dentro de uma função aninhada

React Hooks, como useState, useEffect e useContext, foram projetados para serem chamados no nível superior de um componente funcional ou de uma função de hook personalizada. Eles também só devem ser chamados em componentes funcionais e não em componentes de classe. Essas são as duas principais regras do React Hooks, que garantem que os Hooks sejam usados de forma correta e consistente nos componentes React.

Quando os Hooks são chamados em locais inválidos, você recebe este erro: “react hooks must be called in a react function component or a custom react hook function”. Esse erro do ESLint existe como uma proteção para evitar que os Hooks sejam usados de maneiras que possam causar comportamentos inesperados e bugs em seu aplicativo React.

2 formas de corrigir o erro “React Hooks Must Be Called In a React Function Component or a Custom React Hook Function”

Esse erro pode ser corrigido de várias maneiras, dependendo da situação ou de como você utilizou erroneamente o React Hook.

1. Nunca chame React Hooks em componentes de classe

Os Hooks são projetados para funcionar somente com componentes funcionais ou hooks personalizados, porque eles usam a pilha de chamadas dos componentes funcionais para gerenciar o estado e o ciclo de vida do componente. Os componentes de classe não têm essa pilha de chamadas, portanto, você não pode usar Hooks diretamente neles.

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;

Se fizer isso, você receberá este erro:

React function error
Erro

No entanto, há algumas maneiras de corrigir isso, dependendo da sua preferência. Você pode optar por usar state e setState com componentes de classe, converter o componente em um componente funcional ou usar um componente de ordem superior (HOC).

A. Converta o componente de classe em um componente funcional

A única maneira dos Hooks funcionarem é quando você está usando um componente funcional. Isso ocorre porque os Hooks foram projetados para trabalhar com componentes funcionais.

No exemplo abaixo, o componente de classe anterior é convertido em um componente funcional:

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. Use um componente de ordem superior (HOC)

Uma maneira de usar Hooks em um componente de classe é usar um componente de ordem superior (HOC).

O HOC é uma função que recebe um componente e retorna um novo componente com adereços ou funcionalidades adicionais. Aqui está um exemplo de como usar um HOC para fornecer Hooks a um componente de classe:

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. Uso de estados em um componente de classe

Por fim, suponha que você não queira alterar a sintaxe do seu componente. Você pode decidir usar state e setState em vez 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. Nunca chame React Hooks em uma função aninhada

Uma regra clara do React Hooks é que todos os Hooks devem ser chamados no nível superior de um componente funcional ou de uma função de hook personalizada. Quando você chama um Hook dentro de uma função aninhada, você infringiu a regra.

No exemplo abaixo, o Hook useState é chamado na função handleClick:

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;

Isso gerará o seguinte erro:

Another React error
Exemplo de erro

Você pode corrigir isso movendo o Hook para fora da função, para o nível superior do seu componente funcional:

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;

Resumo

Neste artigo, você aprendeu o que causa o erro “react hooks must be called in a react function component or a custom react hook function” e como corrigi-lo.

Sempre siga as regras dos React Hooks ao trabalhar e utilizá-los em seus projetos React para evitar erros como este.

Você está procurando a solução de hospedagem ideal para seus aplicativos React? Experimente a hospedagem de aplicativos da Kinsta gratuitamente!

Queremos ouvir você! Já encontrou esse erro antes? Se sim, como resolveu? Utilizou alguma abordagem diferente das mencionadas neste artigo? Compartilhe suas opiniões na seção de comentários abaixo!