Saltar al contenido

Errores comunes con efectos

Los tres tropiezos del efecto: escribir un signal que el propio efecto lee y provocar un bucle, usar efectos para derivar estado en vez de un memo, y sincronizar con el mundo externo sin fugas ni lecturas rancias. untrack y on como herramientas.

El bucle: escribir lo que lees

Si un efecto lee un signal y también lo escribe, se dispara a sí mismo: la escritura ensucia una dependencia de la que el propio efecto depende, y el ciclo se realimenta. Solid vigila las actualizaciones desbocadas y llega a lanzar un error de bucle potencial, pero el error es el síntoma; la enfermedad es haber cerrado el lazo.

TSX
// BUG: el efecto lee y escribe `total`, se realimenta sin fincreateEffect(() => {  setTotal(total() + item());});

Hay tres salidas, en orden de preferencia inversa. La más tosca: untrack la lectura, para leer total sin depender de él y cortar el lazo.

TSX
import { untrack } from "solid-js";createEffect(() => {  const i = item();  setTotal(untrack(total) + i); // lee total sin suscribirse});

Funciona, pero delata el verdadero problema: eso no era una reacción, era una derivación. total es función de sus sumandos; expresarlo como un efecto que se muerde la cola es forzar con una herramienta lo que otra hace de forma natural.

No derives estado con efectos

El anti-patrón más extendido es usar un efecto para copiar un signal en otro: leer A, calcular algo y hacer setB. Cada vez que veas un efecto cuyo único trabajo es un setX, casi siempre querías un createMemo.

TSX
// anti-patron: espejar un signal en otro con un efectoconst [nombre, setNombre] = createSignal("Ada");const [saludo, setSaludo] = createSignal("");createEffect(() => setSaludo(`Hola ${nombre()}`));// idiomatico: una derivacion pura, sin estado duplicadoconst saludo = createMemo(() => `Hola ${nombre()}`);

La versión con efecto tiene tres defectos que la de memo no tiene. Introduce un tick de retraso: saludo va un paso por detrás de nombre hasta que corre el efecto. Duplica el estado en dos signals que pueden desincronizarse. Y añade un nodo de escritura al grafo donde bastaba uno de lectura.

El memo, en cambio, es pull: se recalcula solo cuando alguien lo lee y su valor cambió, siempre coherente, sin estado espejo. La regla es nítida: si ambos lados de la sincronización viven dentro de Solid, no quieres un efecto, quieres una derivación.

Sincronizar con el mundo externo, con cuidado

Cuando un lado no es reactivo —el DOM, la red, una suscripción, el localStorage, un log— el efecto sí es la herramienta correcta: es el puente entre el grafo y lo impuro. Persistir un signal en el almacenamiento del navegador es el ejemplo canónico de uso legítimo: uno de los lados, el localStorage, está fuera de Solid.

TSX
// uso correcto: sincronizar estado reactivo con un mundo NO reactivocreateEffect(() => {  localStorage.setItem("tema", tema()); // el destino no es un signal});

Ese efecto no deriva nada ni se muerde la cola: proyecta un valor reactivo hacia fuera. Pero el puente pide tres cautelas.

Primera: limpia siempre. Toda suscripción, temporizador o petición en vuelo debe cancelarse en onCleanup, o acumularás listeners zombis y respuestas que llegan tarde y pisan el estado.

Segunda: lee tus dependencias arriba, de forma síncrona; si lees un signal dentro de un .then o tras un await, ni trackeas ni ves el valor vigente.

Tercera: cuando quieras dependencias explícitas y opcionalmente saltarte el primer run, usa on.

TSX
import { createEffect, on, onCleanup } from "solid-js";createEffect(on(consulta, (q) => {  const ctrl = new AbortController();  buscar(q, ctrl.signal).then(setResultados); // q capturado, sincrono  onCleanup(() => ctrl.abort());              // cancela la peticion vieja}));

on(consulta, fn) declara que este efecto reacciona solo a consulta, aunque dentro leas otros signals: lo demás no lo re-dispara. Y con la opción defer el efecto no corre en el montaje, solo cuando consulta cambia por primera vez de verdad.

TSX
createEffect(on(consulta, (q) => buscar(q), { defer: true }));// no busca al montar; espera al primer cambio real de `consulta`

Es el escape controlado del tracking automático para los casos en que quieres mandar tú.