React
Cuándo no necesitas un Effect
Explica qué cálculos, eventos y transformaciones no necesitan useEffect y cómo reemplazarlos por renderizado, handlers, estado derivado o keys.
- Última actualización
- Actualizada
- Nivel
- Fundamentos
React
Explica qué cálculos, eventos y transformaciones no necesitan useEffect y cómo reemplazarlos por renderizado, handlers, estado derivado o keys.
No los uses para transformar datos que ya tienes.
// Innecesario
useEffect(() => {
setFullName(`${firstName} ${lastName}`);
}, [firstName, lastName]);const fullName = `${firstName} ${lastName}`;function handleSubmit() {
saveOrder(order);
showToast("Guardado");
}No guardes una bandera para que un effect detecte que ocurrió el click.
En lugar de:
useEffect(() => setComment(""), [postId]);puedes usar:
<CommentForm key={postId} postId={postId} />Llama onChange en el mismo evento donde cambia el dato, no en un effect posterior.
Sí requieren effect o APIs especializadas: sockets, DOM no controlado, timers, widgets o almacenamiento externo.
Antes de escribir useEffect, pregunta: “¿con qué sistema externo estoy sincronizando?”.
¿el código sincroniza con algo fuera de React?
├─ sí → effect o API especializada
└─ no
¿ocurre por una interacción concreta?
├─ sí → event handler / Action
└─ no
¿puede calcularse con props y state?
├─ sí → durante render
└─ no → revisar ownership y modeloEste filtro elimina gran parte de los effects innecesarios.
function ProductList({ products, query }: Props) {
const visible = products.filter((product) =>
product.name.toLowerCase().includes(query.toLowerCase()),
);
return <List products={visible} />;
}No necesitas state ni effect. Si el cálculo medido es costoso, considera useMemo, pero conserva la derivación.
function ProfilePage({ userId }: { userId: string }) {
return <ProfileForm key={userId} userId={userId} />;
}La identidad comunica un reset completo. Un effect que llama varios setters produce primero un render con datos anteriores y después otro con el reset.
Para reset parcial dentro de la misma entidad, usa el handler o transición responsable.
A veces quieres preservar parte del state y ajustar otra. Antes de un effect:
Los effects de sincronización prop→state suelen crear estados intermedios y reglas difíciles.
No necesitas un effect para reutilizar código:
function calculateTotal(items: Item[]) {
return items.reduce((sum, item) => sum + item.price, 0);
}Una función pura o custom hook de cálculo puede ejecutarse durante render. Un custom hook no necesita contener effects.
async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
await createOrder(new FormData(event.currentTarget));
}El evento conoce exactamente qué acción ocurrió. Guardar shouldSubmit=true y observarlo con effect añade otra transición y puede repetir operaciones al montar o restaurar state.
function Toggle({ checked, onChange }: Props) {
function handleClick() {
onChange(!checked);
}
return <button onClick={handleClick}>...</button>;
}No mantengas una copia local y luego ejecutes onChange desde effect. Notifica durante la misma interacción para que padre e hijo compartan una transición.
useEffect(() => setScore(calculateScore(cards)), [cards]);
useEffect(() => {
if (score > 100) setLevel((value) => value + 1);
}, [score]);Este modelo transforma datos mediante renders sucesivos. Calcula score durante render y actualiza level en el evento que modificó cards, o modela la transición completa con reducer.
Las cadenas son frágiles porque cada estado intermedio puede activar otra regla.
Código que debe ejecutarse una vez por carga del módulo puede vivir fuera de React:
initializeMonitoring();Hazlo solo si es seguro en el entorno y no depende de una instancia. Código que necesita lifecycle del componente sí pertenece a effect.
Una suscripción externa requiere sincronización, pero useSyncExternalStore suele ser más correcto que state + effect manual:
const snapshot = useSyncExternalStore(
store.subscribe,
store.getSnapshot,
store.getServerSnapshot,
);Elegir una API especializada también cuenta como eliminar un effect manual.
Registrar una vista puede ser sincronización con un sistema externo y usar effect según el router y lifecycle. Registrar un click pertenece al handler del click. Diferencia “la pantalla quedó visible” de “el usuario pulsó el botón”.
Leer localStorage para inicializar state puede usar lazy initialization en cliente:
const [theme, setTheme] = useState(() => readStoredTheme());Escribir cuando cambia theme puede ser un effect porque sincroniza con storage. En SSR debes diseñar un valor inicial consistente y evitar acceder a window en servidor.
Preguntas:
Si no puedes completar “sincroniza con ___”, probablemente no necesitas effect.
useSyncExternalStore bajo un contrato de snapshot.useLayoutEffect y medición del layout cubre un effect especializado para trabajo visual antes del paint.