Saltar al contenido

Qué es un efecto y cuándo corre

createEffect crea una reacción: una computación que se re-ejecuta cuando cambian sus dependencias. Corre tras el render, en la cola de efectos, agrupada por lotes, y siempre con un primer run que lo arranca todo.

Un efecto es una hoja del grafo

El grafo reactivo tiene tres clases de nodo. Los signals son fuentes: no dependen de nadie, solo emiten. Los memos son intermedios: dependen de otros nodos y a la vez pueden ser leídos. Los efectos son sumideros: dependen de otros nodos, pero nadie los lee, porque no devuelven un valor útil al grafo.

Por eso los efectos son hojas. Su trabajo no es producir un dato sino ejecutar un efecto secundario cada vez que su entrada cambia. Todo lo que en una interfaz “sale” del sistema reactivo —un log, una mutación del DOM, una petición— vive en un efecto.

createEffect recibe una función y la convierte en esa hoja. Al leer un signal dentro de ella, el efecto queda suscrito; cuando el signal cambie, el efecto volverá a correr.

TSX
import { createSignal, createEffect } from "solid-js";function Contador() {  const [n, setN] = createSignal(0);  createEffect(() => {    console.log("n vale", n());  });  return <button onClick={() => setN(n() + 1)}>{n()}</button>;}

El cuerpo del componente corre una sola vez —Solid no re-renderiza—, así que createEffect no se registra en cada render como en React. Se registra una vez y a partir de ahí vive por su cuenta, reaccionando a n mientras exista.

El primer run: la chispa

Todo efecto corre al menos una vez. Ese primer run no es opcional: es el momento en que el efecto ejecuta su función por primera vez, lee sus signals y así descubre de quién depende. Sin él no habría suscripciones y el efecto nunca reaccionaría a nada.

La sutileza está en cuándo ocurre. En createEffect, el primer run se difiere hasta después del render inicial: Solid crea primero el DOM y solo entonces vacía la cola de efectos. Por eso dentro de un efecto el DOM ya existe y las refs ya apuntan a nodos reales.

TSX
function Perfil() {  let caja: HTMLDivElement | undefined;  createEffect(() => {    // el primer run ocurre despues del render:    // `caja` ya apunta al div real, nunca a undefined    console.log(caja?.offsetHeight);  });  return <div ref={caja}>contenido</div>;}

Es el análogo fino de un useEffect con dependencias vacías, pero sin lista que mantener y sin re-registro en cada render.

La cola de reacciones

En las ejecuciones siguientes, una escritura no dispara el efecto en el acto. Solid marca los observadores como obsoletos, recomputa primero las computaciones puras —memos y computeds— y solo al final vacía la cola de efectos.

El efecto corre así sobre un grafo ya consistente, nunca a medio actualizar. Ese orden —marcar, recomputar puros, vaciar efectos— es la ley que gobierna todo el sistema.

Batched: una reacción por lote

Solid no re-ejecuta un efecto por cada escritura, sino una vez por lote. Dentro de un manejador de eventos, todas las escrituras se agrupan automáticamente: aunque toques tres signals que el efecto observa, correrá una sola vez, al terminar el manejador.

TSX
const [x, setX] = createSignal(0);const [y, setY] = createSignal(0);createEffect(() => console.log("suma", x() + y()));function mover() {  setX(10);  setY(20);  // el efecto corre UNA vez con x=10, y=20; jamas ve el estado intermedio}

Fuera de un manejador, si necesitas agrupar escrituras a mano, envuélvelas en batch. La garantía es la misma en ambos casos.

TSX
import { batch } from "solid-js";batch(() => {  setX(1);  setY(2);}); // una sola reaccion al cerrar el lote

Un efecto jamás observa un estado a medio construir: ve el antes o el después de un lote, nunca el durante. Esta propiedad —ausencia de estados intermedios visibles— es lo que en la literatura reactiva se llama ser glitch-free, y es lo que hace fiable razonar sobre un efecto: lo que lees dentro es siempre coherente entre sí.