cd /news/developer-tools/como-solucionar-el-bucle-infinito-en… · home topics developer-tools article
[ARTICLE · art-11204] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Cómo solucionar el bucle infinito en useEffect con objetos y arrays

The article explains that infinite loops in React's `useEffect` occur because it uses reference equality (`===`) to compare dependencies, so a new object created by `useState({})` is always considered a change. Solutions include removing the dependency with an empty array `[]`, using `JSON.stringify` for content comparison, or employing `useMemo` to create a stable primitive value. The article warns that `JSON.stringify` is costly for large objects and cannot handle functions, `undefined`, or circular references.

read2 min views20 publishedMay 23, 2026

Explicación técnica #

El problema ocurre porque useEffect

compara los valores de las dependencias usando comparación de referencia ( ===), no por contenido (deep equality). 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

), lo que dispara la reejecución del useEffect

, causando el bucle infinito.En tu caso:

const [ingredients, setIngredients] = useState({});
useEffect(() => {
  setIngredients({}); // ¡Crea un nuevo objeto!
}, [ingredients]); // ingredients cambia de referencia → reejecuta → loop infinito

Pasos para solucionarlo #

Opción 1: Evitar la actualización innecesaria (recomendada)

Si no necesitas actualizar el estado dentro del useEffect

, elimina la dependencia del objeto/array y usa un array vacío:

useEffect(() => {
  // Solo ejecutar al montar el componente
  setIngredients({});
}, []); // ✅ Sin dependencias → solo se ejecuta una vez

Opción 2: Comparación profunda manual

Si necesitas ejecutar el useEffect

solo cuando el contenido cambia, usa JSON.stringify

(para objetos simples sin funciones/circularidades):

useEffect(() => {
  setIngredients({});
}, [JSON.stringify(ingredients)]); // ✅ Compara contenido, no referencia

⚠️ Advertencia: JSON.stringify

es costoso en objetos grandes y falla con funciones, undefined

, o referencias circulares.

Opción 3: Usar useMemo

para una representación estable

Crea una representación estable del objeto (ej. número de elementos, hash):

const ingredientsHash = useMemo(() => 
  Object.keys(ingredients).length, // o tu lógica personalizada
  [ingredients]
);

useEffect(() => {
  setIngredients({});
}, [ingredientsHash]); // ✅ Compara valor primitivo estable

Opción 4: Validar si el valor es distinto antes de actualizar

Evita la actualización si el contenido es idéntico:

useEffect(() => {
  if (Object.keys(ingredients).length > 0) {
    setIngredients({});
  }
}, [ingredients]); // ✅ Solo actualiza si no está vacío

Bloque de código corregido (recomendado) #

const [ingredients, setIngredients] = useState({});

useEffect(() => {
  // Solo ejecutar al montar el componente (ej. limpiar estado inicial)
  setIngredients({});
}, []); // ✅ Solución definitiva para este caso

Pro-tip #

Nunca actualices el mismo estado que usas como dependencia sin una lógica de comparación profunda. - Para objetos complejos, usa librerías como immer

ouseDeepCompareEffect

(deuse-deep-compare-effect

) si necesitas comparación profunda segura. - Si el objetivo es limpiar el estado al montar, usa useEffect

con[]

y no actualices el estado dentro. En su lugar, inicializa el estado con el valor deseado desde el inicio:

const [ingredients, setIngredients] = useState({}); // ✅ Inicialización directa
── more in #developer-tools 4 stories · sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/como-solucionar-el-b…] indexed:0 read:2min 2026-05-23 ·