Cómo solucionar el bucle infinito en useEffect con objetos y arrays
Explicación técnica
El problema ocurre porque useEffect compara las dependencias usando comparación por 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) y vuelve a ejecutar el efecto, causando el bucle infinito.
En tu caso:
const [ingredients, setIngredients] = useState({});
useEffect(() => {
setIngredients({}); // ← ¡Crea un nuevo objeto!
}, [ingredients]); // ← Siempre es una referencia diferente → bucle infinito
Solución definitiva (3 enfoques)
Opción 1: Usar estado funcional + comparación profunda (recomendada)
useEffect(() => {
setIngredients(prev => {
// Solo actualiza si el contenido realmente cambió
if (Object.keys(prev).length > 0) {
return {};
}
return prev;
});
}, []); // ← Sin dependencias: solo ejecuta al montar
Opción 2: Comparar contenido manualmente con useDeepCompareEffect
// Implementa una comparación profunda personalizada
function useDeepCompareEffect(callback, dependencies) {
useEffect(() => {
callback();
}, [dependencies.map(dep => JSON.stringify(dep))]);
}
// Uso:
useDeepCompareEffect(() => {
setIngredients({});
}, [ingredients]);
Opción 3: Usar useReducer para lógica compleja (mejor práctica)
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' });
}, []); // ← Sin dependencias
Bloque de código corregido (recomendado)
import { useState, useEffect } from 'react';
function MyComponent() {
const [ingredients, setIngredients] = useState({});
useEffect(() => {
// Solo resetea si el objeto no está vacío
setIngredients(prev =>
Object.keys(prev).length > 0 ? {} : prev
);
}, []); // ← Sin dependencias para evitar bucles
return (
<div>
<p>Ingredients: {JSON.stringify(ingredients)}</p>
</div>
);
}
Pro-tip: Regla de oro para objetos y arrays en useEffect
Nunca incluyas objetos/arrays directamente en las dependencias si vas a crear nuevos objetos/arrays dentro del efecto.
En su lugar:
- Usa
[]si la lógica solo necesita ejecutarse al montar/desmontar- Usa comparación profunda para dependencias dinámicas
- Considera
useReducerpara estados complejos- Para validaciones simples, compara propiedades específicas (ej:
ingredients.lengthen lugar del array completo)
Top comments (0)