Cómo solucionar el bucle infinito en useEffect con objetos y arrays
Explicación técnica (por qué ocurre)
El problema ocurre porque useEffect compara los valores de las dependencias usando comparación de referencia (===), no por contenido. Cuando usas useState({}), cada llamada a setObj({}) crea un nuevo objeto en memoria, aunque tenga el mismo contenido. React detecta que la referencia cambia (obj !== obj), por lo que vuelve a ejecutar el efecto, causando el bucle infinito.
En tu caso:
const [ingredients, setIngredients] = useState({});
useEffect(() => {
setIngredients({}); // ¡Crea un nuevo objeto!
}, [ingredients]); // ingredients cambia de referencia → efecto se vuelve a ejecutar
Pasos para solucionarlo
Opción 1: Evitar la actualización innecesaria (recomendada)
Verifica si el estado ya tiene el valor deseado antes de actualizarlo:
useEffect(() => {
if (Object.keys(ingredients).length > 0) {
setIngredients({});
}
}, [ingredients]);
Opción 2: Usar comparación profunda con useDeepCompareEffect (para casos complejos)
Instala la librería use-deep-compare-effect:
npm install use-deep-compare-effect
Y reemplaza useEffect:
import useDeepCompareEffect from 'use-deep-compare-effect';
useDeepCompareEffect(() => {
setIngredients({});
}, [ingredients]);
Opción 3: Usar useReducer para lógica de estado compleja
const initialState = {};
function reducer(state, action) {
switch (action.type) {
case 'reset':
return {};
default:
return state;
}
}
const [ingredients, dispatch] = useReducer(reducer, initialState);
useEffect(() => {
dispatch({ type: 'reset' });
}, [ingredients]);
Opción 4: Normalizar el estado (recomendada para arrays/objetos grandes)
Convierte el objeto/array en un valor primitivo para las dependencias:
const [ingredients, setIngredients] = useState({});
const ingredientsKey = JSON.stringify(ingredients);
useEffect(() => {
if (ingredientsKey !== '{}') {
setIngredients({});
}
}, [ingredientsKey]);
Bloque de código corregido (solución definitiva)
import { useState, useEffect } from 'react';
function Component() {
const [ingredients, setIngredients] = useState({});
useEffect(() => {
// Solo actualiza si no está vacío
if (Object.keys(ingredients).length > 0) {
setIngredients({});
}
}, [ingredients]);
return (
// tu JSX aquí
);
}
Pro-tip
- Nunca uses
useEffect(() => {}, [obj])con objetos mutables sin validación previa - Para objetos simples, usa
JSON.stringify()como dependencia (con cuidado con rendimiento) - Para lógica compleja, considera
useReducero librerías comoimmerpara manejar inmutabilidad - Si solo necesitas limpiar el estado al montar el componente, usa un array vacío:
useEffect(() => { ... }, [])
Top comments (0)