Saltar al contenido

onMount: el trabajo que espera al DOM

Cuándo corre onMount (una sola vez, tras el render inicial y solo en el cliente), para qué sirve (el nodo ya está adjunto al documento: enfocar, medir, instanciar librerías) y por qué por dentro no es más que un createEffect cuyo cuerpo va envuelto en untrack: un efecto que no rastrea nada y por eso jamás se repite.

Un disparo único después del montaje

El cuerpo de un componente Solid corre una sola vez y construye el JSX en memoria; en ese instante los nodos existen como objetos, pero todavía nadie los ha insertado en la página. onMount registra una función que Solid ejecutará después: cuando el árbol devuelto ya está adjunto al documento.

TSX
import { onMount } from "solid-js";function Buscador() {  let entrada!: HTMLInputElement;  onMount(() => {    entrada.focus();          // el nodo ya vive en la pagina    entrada.select();  });  return <input ref={entrada} placeholder="buscar" />;}

Enfocar exige que el elemento esté en pantalla; medir exige que tenga geometría; ambas cosas solo son ciertas tras la inserción. Por eso todo lo que toca el DOM real va en onMount, no junto a la declaración del ref. Si intentas leer el nodo en el cuerpo, aún no existe:

TSX
function Roto() {  let caja!: HTMLDivElement;  const ancho = caja.offsetWidth;   // TypeError: caja es undefined aqui  return <div ref={caja} />;}

onMount es también el lugar natural para arrancar trabajo asíncrono de inicialización que solo importa en el cliente: cargar datos, pedir permisos, abrir una conexión. Como corre tras el montaje y solo en el navegador, no bloquea el render inicial ni se ejecuta en el servidor.

TSX
function Perfil() {  onMount(async () => {    const datos = await fetch("/api/perfil").then((r) => r.json());    aplicar(datos);           // el componente ya esta en pantalla  });  return <section>...</section>;}

onMount corre una vez y nunca más. No es un lugar para reaccionar a cambios de estado —eso es trabajo de los efectos—, sino para el trabajo de arranque que solo tiene sentido cuando el componente acaba de aparecer.

Por qué el DOM ya existe aquí

La clave está en el orden de fases del runtime. Primero corre el cuerpo y se crean los nodos; luego el runtime los inserta en el documento; y solo entonces se vacía la cola de efectos diferidos, entre ellos onMount.

Esa posición al final de la secuencia es lo que garantiza el DOM. Y también explica dos límites: en SSR, donde no hay documento, onMount no corre en el servidor; solo se dispara en el cliente. Por eso cualquier acceso al nodo —medir, enfocar, observar— debe vivir aquí y no en el cuerpo, que sí se ejecuta en el servidor, donde no hay nodo que capturar.

onMount por dentro: un efecto que no rastrea nada

Aquí está la revelación que ordena todo el nivel. onMount no es una primitiva especial del scheduler: es azúcar sobre createEffect. Su definición completa cabe en una línea.

TSX
// Asi lo define Solid, sin magia oculta:export function onMount(fn: () => void): void {  createEffect(() => untrack(fn));}

Un createEffect corriente ya corre después del montaje —como toda la cola de efectos— y se re-ejecuta cuando cambia algún signal que lee. El único añadido de onMount es envolver tu función en untrack: dentro de untrack ninguna lectura reactiva crea una suscripción. Sin suscripciones, no hay nada que dispare un segundo run. El efecto corre una vez y queda inerte.

Por eso “efecto sin dependencias” es literal, no metafórico. En React, useEffect(fn, []) declara un array vacío que una regla de lint vigila y que el runtime compara en cada render; el “no repetir” es una convención sobre datos. En Solid no hay array ni comparación: la ausencia de dependencias es estructural, consecuencia física de que untrack impide que se forme cualquier arista en el grafo.

Ese untrack solo alcanza las lecturas síncronas del cuerpo de onMount. Si dentro creas un createEffect anidado, ese efecto tiene su propio ámbito de rastreo y reacciona con normalidad: la envoltura no se hereda hacia los cómputos hijos. Es justo lo que permite instanciar una librería en onMount y, dentro, registrar efectos que sincronizan props —el patrón que cierra este nivel.

onMount frente a otros timings

onMount no es el único punto posterior al cuerpo. Solid distingue los efectos por cuándo corren respecto al pintado del navegador. createRenderEffect corre durante la fase de render, antes de pintar; createEffect —y por tanto onMount— corre después, con el árbol ya insertado. Para medir o enfocar quieres el segundo, porque el nodo debe estar adjunto.

TSX
import { createRenderEffect, createEffect } from "solid-js";createRenderEffect(() => console.log("render: el DOM puede no estar conectado aun"));createEffect(() => console.log("post-render: el DOM ya esta insertado"));

Un createRenderEffect que mida offsetWidth puede leer cero porque corre antes de la inserción. La regla se mantiene: para tocar geometría, foco u observadores, siempre onMount.