Skip to content
article

useEffect no es para todo: 5 cosas que hacía mal y cómo las arreglé

basado en 'You Might Not Need an Effect' de la doc de React, pero con ejemplos reales de mi camello

Camilo Restrepo@camilo_parce

September 17, 2026 · 3 min read

Parce, hace un año revisé un proyecto mío viejo y conté 43 useEffect. Hoy tiene 9. Y funciona mejor. Les cuento los 5 errores que más cometía, por si se ven reflejados.

1. Estado derivado en un efecto

// mal
const [nombreCompleto, setNombreCompleto] = useState('')
useEffect(() => {
  setNombreCompleto(nombre + ' ' + apellido)
}, [nombre, apellido])

// bien
const nombreCompleto = nombre + ' ' + apellido

Si algo se puede calcular con lo que ya tienes, calcúlalo durante el render. El efecto hace que el componente se pinte dos veces: una con el valor viejo y otra con el nuevo.

2. Filtrar una lista en un efecto

// bien
const visibles = todos.filter(t => t.hecho === mostrarHechos)

// y si la lista es enorme y el filtro es caro:
const visibles = useMemo(
  () => todos.filter(t => t.hecho === mostrarHechos),
  [todos, mostrarHechos]
)

Ojo: useMemo solo cuando lo mediste y de verdad es caro. No lo pongan en todo "por si acaso".

3. La lógica de un evento metida en un efecto

// mal: mandar el POST cuando cambia un estado
useEffect(() => {
  if (enviado) {
    fetch('/api/pedido', { method: 'POST', body: JSON.stringify(pedido) })
  }
}, [enviado])

// bien: mandarlo donde pasa la acción
function handleSubmit() {
  fetch('/api/pedido', { method: 'POST', body: JSON.stringify(pedido) })
}

La pregunta clave: ¿esto pasa porque el componente se mostró, o porque el usuario hizo algo? Si es lo segundo, va en el handler.

4. Resetear estado cuando cambia una prop

// mal
useEffect(() => {
  setComentario('')
}, [userId])

// bien: que React lo trate como otro componente
<Perfil key={userId} userId={userId} />

Con una key distinta, React desmonta y vuelve a montar. Todo el estado interno arranca limpio. Es el truco más subestimado de React, pues.

5. Fetch sin limpieza (race conditions)

Este es el que más bugs me dio. El usuario cambia rápido de perfil, la respuesta vieja llega después de la nueva y te muestra el nombre equivocado.

useEffect(() => {
  let ignorar = false
  fetch('/api/usuarios/' + id)
    .then(res => res.json())
    .then(data => {
      if (!ignorar) setUsuario(data)
    })
  return () => {
    ignorar = true
  }
}, [id])

También se puede con AbortController. Y para una app de verdad, usen TanStack Query o SWR, que ya resuelven caché, reintentos y todo esto.

Bonus: "¡mi efecto corre dos veces!"

En desarrollo, con StrictMode, React monta, desmonta y vuelve a montar a propósito, para que encuentres efectos sin limpieza. En producción corre una vez. No quiten el StrictMode.

La fuente de casi todo esto es la doc oficial, que está buenísima y en inglés sencillo: You Might Not Need an Effect. Léanla completa, vale la pena.

Written by

Camilo Restrepo

Fullstack dev en Medellín 🇨🇴 React, Node, Postgres. Trabajo remoto pa' empresas gringas. Parce, si necesitás algo, me escribís.

Get the best of #codigo_en_espanol weekly

One email each Monday with the most useful posts. No spam; unsubscribe in one click.

Comments

9

Sign in to join the conversation.

Sign in to comment
Sofía Ramírez@sofi_dev_mx#1 in Código en Español
El #4 con key es el truco más subestimado de React, lo uso cada semana. Buen post parce 💜 (ya ves, aprendo paisa)
6 net votes
Camilo Restrepo@camilo_parce#3 in Código en Español
jajaja 'parce' con acento tapatío, me encanta
3 net votes
Luis Treviño@luis_qa_mty#8 in Código en Español
desde QA: el #5 es el bug que más reporto. el usuario cambia rápido de perfil y aparece el nombre del anterior. le digo 'race condition' y el dev me dice 'en mi máquina sí jala' 🤣
1 net votes
Daniela Castaño@dani_ctf2 rep in Código en Español
Muy claro. Aunque usted sabe que lo de Medellín es solo React y fiestas, ¿cierto? 😏 Buen post, eso no se lo voy a negar.
5 net votes
Camilo Restrepo@camilo_parce#3 in Código en Español
Dani, al menos en Medellín el React funciona. En Bogotá con ese frío ni compila jajaja
0 net votes
Iván Ochoa@ivan_tj1 rep in Código en Español
Bro el #1 lo tenía en todo un proyecto. Literal un useEffect por cada campo del form. Ya lo estoy borrando, gracias carnal
1 net votes
Ben Carter@bencarter_web1 rep in Código en Español
Leí esto en español para practicar (I am learning). El ejemplo de ignorar = true es perfecto, I normally use AbortController but this is way easier to explain to clients.
1 net votes
Lucía Ferrer@lucia_ferrer_dev#6 in Código en Español
Acabo de encontrar este post y el número 1 lo tengo en mi primer PR en el curro jajaja!! Lo cambio mañana antes de que lo vea mi tech lead xD gracias!!
1 net votes
Camilo Restrepo@camilo_parce#3 in Código en Español
Jajaja tranquila Lucía, todos lo hicimos. Que tu tech lead no se entere 🤫
2 net votes