惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

月光博客
月光博客
C
Check Point Blog
J
Java Code Geeks
腾讯CDC
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
Microsoft Azure Blog
Microsoft Azure Blog
WordPress大学
WordPress大学
量子位
Google DeepMind News
Google DeepMind News
I
InfoQ
The GitHub Blog
The GitHub Blog
aimingoo的专栏
aimingoo的专栏
N
Netflix TechBlog - Medium
Hugging Face - Blog
Hugging Face - Blog
博客园 - Franky
V
V2EX
Blog — PlanetScale
Blog — PlanetScale
T
The Blog of Author Tim Ferriss
小众软件
小众软件
博客园_首页
人人都是产品经理
人人都是产品经理
博客园 - 聂微东
IT之家
IT之家

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Cómo solucionar el bucle infinito en `useEffect` con obje...
Erick Eduard · 2026-05-24 · via DEV Community

Erick Eduardo Ramos

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

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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]);

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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>
  );
}

Enter fullscreen mode Exit fullscreen mode

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 useReducer para estados complejos
  • Para validaciones simples, compara propiedades específicas (ej: ingredients.length en lugar del array completo)