Los Hooks de React han revolucionado la forma de escribir componentes funcionales en React, proporcionando una forma concisa y potente de gestionar el estado y los efectos secundarios.

Sin embargo, como ocurre con cualquier característica nueva, viene con su propio conjunto de reglas y directrices. Un error común con el que se pueden encontrar los desarrolladores de React es el de «react hooks must be called in a react function component or a custom react hook function» (los hooks de react deben ser llamados dentro de un componente de función de react o una función de hook personalizado de react).

En este artículo, profundizaremos en los detalles de este error, comprenderemos por qué se produce y proporcionaremos las mejores prácticas para solucionarlo.

¿Qué Causa el Error «React Hooks Must Be Called In a React Function Component or a Custom React Hook Function»?

Hay reglas relacionadas con el uso de React Hooks. Muchos desarrolladores React se saltan estas reglas cuando aprenden React, lo que conduce a errores. Uno de estos errores es «react hooks must be called in a react function component or a custom react hook function».

Este error se produce cuando ocurren dos cosas importantes

  • Usar React Hooks en componentes de clase
  • Llamar a React Hooks dentro de una función anidada

Los React Hooks, como useState, useEffect, y useContext, están diseñados para ser llamados en el nivel superior de un componente funcional o de una función hook personalizada. Además, sólo deben invocarse en componentes funcionales y no en componentes de clase. Estas son dos reglas principales de los React Hooks, que garantizan que los Hooks se utilicen de forma correcta y coherente en los componentes React.

Cuando los Hooks se llaman en lugares no válidos, se obtiene este error «react hooks must be called in a react function component or a custom react hook function». existe como una medida de seguridad para evitar que los Hooks se utilicen de formas que puedan causar comportamientos inesperados y fallos en tu aplicación React.

2 Formas de Solucionar el Error «React Hooks Must Be Called In a React Function Component or a Custom React Hook Function»

Este error puede solucionarse de varias maneras, dependiendo de la situación o de cómo hayas utilizado incorrectamente el React Hook.

1. Nunca Llames a React Hooks en Componentes de Clase

Los Hooks están diseñados para funcionar sólo con componentes funcionales o ganchos personalizados —  porque utilizan el stack de llamadas de los componentes funcionales para gestionar el estado y el ciclo de vida del componente. Los componentes de clase no tienen este stack de llamadas, por lo que no puedes utilizar Hooks directamente en ellos.

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;

Si lo haces, obtendrás este error:

Error en la función React
Error

Sin embargo, hay algunas formas de solucionarlo, dependiendo de tus preferencias. Puedes decidir utilizar state y setState con componentes de clase, convertir el componente en un componente funcional o utilizar un Higher-Order Component (HOC) o Componente de Orden Superior.

A. Convertir el Componente de Clase en un Componente Funcional

La única forma en que pueden funcionar los Hooks es cuando utilizas un componente funcional. Esto se debe a que los Hooks están diseñados para trabajar con componentes funcionales.

En el ejemplo siguiente, el componente de clase anterior se convierte en un 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. Utilizar un Componente de Orden Superior (Higher-Order Component (HOC)

Una forma de utilizar Hooks en un componente de clase es utilizar un Componente de Orden Superior (HOC).

Un HOC es una función que toma un componente y devuelve un nuevo componente con accesorios o funciones adicionales. Aquí tienes un ejemplo de cómo utilizar un HOC para proporcionar Hooks a un componente de clase:

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. Utilizar Estados en un Componente de Clase

Por último, supongamos que no quieres cambiar la sintaxis de tu componente. Puedes decidir utilizar state y setState en lugar del Hook useState:

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 Llames a React Hooks Dentro de una Función Anidada

Una regla clara de los React Hooks es que todos los Hooks deben llamarse al nivel superior de un componente funcional o de una función hook personalizada. Cuando llamas a un Hooks dentro de una función anidada, has infringido la regla.

En el ejemplo siguiente, el Hook useState se llama en la función 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;

Esto arrojará el siguiente error:

Otro error de React
Ejemplo de error

Puedes solucionarlo moviendo el Hook fuera de la función — al nivel superior de tu 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;

Resumen

En este artículo, has aprendido qué causa el error «react hooks must be called in a react function component or a custom react hook function» (los hooks de react deben llamarse en un componente funcional de react o en una función de hook de react personalizada), y cómo puede solucionarse.

Sigue siempre las reglas de los hooks de React cuando trabajes y los utilices en tus proyectos React para evitar experimentar errores como éste.

¿Buscas la solución de alojamiento ideal para tus aplicaciones React? ¡Prueba gratis el alojamiento de Aplicaciones de Kinsta!

¡Queremos conocer tu opinión! ¿Has experimentado alguna vez este error? Si es así, ¿cómo lo resolviste? ¿Has utilizado algún otro método que no se haya mencionado en este artículo? Comparte tu opinión en la sección de comentarios más abajo.