Reglas de los Hooks
Probablemente estás aquí porque te ha aparecido el siguiente mensaje de error:
Este mensaje puede aparecer por tres motivos comunes:
- Estás incumpliendo las Reglas de los Hooks.
- Estás usando versiones incompatibles de React y React DOM.
- Estás usando más de una instancia de React en la misma aplicación.
Veamos cada uno de estos casos.
Incumplir las Reglas de los Hooks
Las funciones que comienzan con use
se conocen como Hooks en React.
Evita utilizar Hooks dentro de ciclos, condicionales o funciones anidadas. En su lugar, utiliza los Hooks únicamente en el nivel superior de tu función de React, antes de cualquier devolución anticipada. Los Hooks sólo deben ser utilizados durante la renderización de un componente de función en React:
- ✅ Utilízalos en el nivel superior del cuerpo de un componente de función.
- ✅ Utilízalos en el nivel superior del cuerpo de un Hook personalizado.
function Counter() {
// ✅ Correcto: en la parte superior de un componente de función
const [count, setCount] = useState(0);
// ...
}
function useWindowWidth() {
// ✅ Correcto: en la parte superior de un Hook personalizado
const [width, setWidth] = useState(window.innerWidth);
// ...
}
No se permite el uso de Hooks (funciones que comienzan con use
) en ningún otro caso, por ejemplo:
- 🔴 Dentro de condicionales o ciclos.
- 🔴 Después de una declaración de
return
condicional. - 🔴 En controladores de eventos.
- 🔴 En componentes de clase.
- 🔴 Dentro de funciones pasadas a
useMemo
,useReducer
, ouseEffect
.
Incumplir estas reglas podría provocar la aparición de este error.
function Bad({ cond }) {
if (cond) {
// 🔴 Incorrecto: dentro de una condicional (para solucionarlo, ¡colócalo fuera!)
const theme = useContext(ThemeContext);
}
// ...
}
function Bad() {
for (let i = 0; i < 10; i++) {
// 🔴 Incorrecto: dentro de un ciclo (para solucionarlo, ¡colócalo fuera!)
const theme = useContext(ThemeContext);
}
// ...
}
function Bad({ cond }) {
if (cond) {
return;
}
// 🔴 Incorrecto: después de una devolución condicional (para solucionarlo, ¡colócalo antes de la devolución!)
const theme = useContext(ThemeContext);
// ...
}
function Bad() {
function handleClick() {
// 🔴 Incorrecto: dentro de un controlador de evento (para solucionarlo, ¡colócalo fuera!)
const theme = useContext(ThemeContext);
}
// ...
}
function Bad() {
const style = useMemo(() => {
// 🔴 Incorrecto: dentro de useMemo (para solucionarlo, ¡colócalo fuera!)
const theme = useContext(ThemeContext);
return createStyle(theme);
});
// ...
}
class Bad extends React.Component {
render() {
// 🔴 Incorrecto: dentro de un componente de clase (para solucionarlo, ¡escribe un componente de función en lugar de uno de clase!)
useEffect(() => {})
// ...
}
}
Puedes usar el plugin de eslint-plugin-react-hooks
para detectar estos errores.
Uso de versiones incompatibles de React y React DOM
Puede que estés usando versiones antiguas de react-dom
(< 16.8.0) o react-native
(< 0.59) que no sean compatibles con Hooks. Para verificar la versión que estás utilizando, puedes ejecutar npm ls react-dom
o npm ls react-native
en la carpeta de tu aplicación. Si encuentras más de una versión instalada, esto podría causar problemas (más información a continuación).
Uso de más de una instancia de React
Para que los Hooks funcionen correctamente, la importación de react
en el código de tu aplicación debe apuntar al mismo módulo que la importación de react
en el paquete react-dom
.
Si estas importaciones de react
apuntan a dos objetos de importación diferentes, verás esta advertencia. Esto puede ocurrir si por error tienes dos copias del paquete react
.
Si usas Node para gestionar paquetes, puedes verificar esto en la carpeta de tu proyecto ejecutando:
Si detectas más de una instancia de React, tendrás que investigar las causas y corregir tu árbol de dependencias. Es posible que alguna biblioteca que estés utilizando especifique incorrectamente react
como una dependencia en lugar de una dependencia entre pares. Mientras se soluciona este problema en la biblioteca, una posible solución temporal es utilizar resoluciones de Yarn.
Para solucionar el problema, puedes intentar depurarlo agregando logs y reiniciando el servidor de desarrollo:
// Añade esto en node_modules/react-dom/index.js
window.React1 = require('react');
// Añade esto en el archivo de tu componente
require('react-dom');
window.React2 = require('react');
console.log(window.React1 === window.React2);
Si imprime false
, es posible que tengas dos instancias de React y debas investigar las posibles causas. Este issue incluye algunas razones comunes encontradas por la comunidad.
Este problema también puede surgir al utilizar npm link
u otro método equivalente, lo que hace que el empaquetador de módulos «vea» dos versiones de React — una en la carpeta de la aplicación y otra en la carpeta de la biblioteca. Si myapp
y mylib
son carpetas hermanas, una posible solución es ejecutar npm link ../myapp/node_modules/react
desde mylib
. De esta forma, la biblioteca utilizará la versión de React de la aplicación.
Otras causas
Si ninguna de estas soluciones funcionó, por favor coméntalo en este issue y trataremos de ayudarte. Intenta crear un pequeño ejemplo que reproduzca el problema — Es posible que descubras la causa del problema mientras intentas reproducirlo.