¿Qué es SolidJS?
SolidJS es una librería de UI declarativa que se parece a React pero funciona de manera muy diferente. Utiliza JSX y componentes, sin embargo, no tiene virtual DOM y no realiza re-renders. En su lugar, utiliza reactividad de grano fino (fine-grained reactivity): los signals rastrean quién los lee y, cuando un valor cambia, solo se actualizan los nodos del DOM y los cálculos que dependen de él.
El efecto práctico es que la función de un componente de Solid se ejecuta exactamente una vez. Todo lo reactivo en su interior se conecta durante esa ejecución y luego se actualiza de forma quirúrgica. Una vez que entiendes este concepto, tanto el rendimiento de Solid como sus reglas cobran sentido.
Signals
Un signal es un valor reactivo creado con createSignal. Devuelve un getter y un setter.
// Counter.jsx
import { createSignal } from "solid-js";
export function Counter() {
const [count, setCount] = createSignal(0);
return (
<button onClick={() => setCount((c) => c + 1)}>
Count: {count()}
</button>
);
}
Para leer un signal, debes llamarlo: count(). Esa llamada es la que registra la dependencia. Pasar una función al setter (setCount((c) => c + 1)) es la forma segura de actualizar el valor basándose en el valor anterior.
Valores derivados con createMemo
createMemo calcula un valor a partir de otros signals y lo almacena en caché. Solo se vuelve a calcular cuando cambia una dependencia, y el resultado se comparte entre todos los lectores.
// cart.jsx
import { createSignal, createMemo } from "solid-js";
const [items, setItems] = createSignal([{ price: 10 }, { price: 20 }]);
const total = createMemo(() =>
items().reduce((sum, item) => sum + item.price, 0),
);
Para expresiones simples en línea también puedes usar una función convencional, pero createMemo evita repetir tareas costosas. Utilízalo cuando el cálculo sea pesado o se lea en varios lugares.
Effects
createEffect ejecuta un efecto secundario cada vez que cambian las señales que lee. Se utiliza para sincronizarse con el mundo exterior, no para calcular valores.
// title.jsx
import { createEffect, createSignal } from "solid-js";
const [name, setName] = createSignal("Ada");
createEffect(() => {
document.title = `Hello, ${name()}`;
});
Los efectos se ejecutan después del renderizado y rastrean sus dependencias automáticamente. Usa onCleanup para limpiar suscripciones, temporizadores y peticiones.
Los componentes se ejecutan una sola vez
Esta es la regla que suele confundir a los desarrolladores de React. Un componente de Solid se ejecuta una única vez. Es una función de configuración que crea vínculos reactivos, no una función que se vuelve a ejecutar cuando cambia el estado.
function Profile(props) {
// Do not destructure props — that breaks reactivity.
// Read them where you use them instead.
return <h1>{props.user.name}</h1>;
}
Debido a que las props son getters reactivos, léelas donde las utilices (props.user.name) en lugar de desestructurarlas. Lo mismo ocurre con los signals: llámalos dentro del JSX o dentro de un memo, no una sola vez al principio del componente.
Componentes de flujo de control
Solid utiliza componentes en lugar de directivas de plantilla para los condicionales y las listas, lo que mantiene todo en JavaScript y permite que el compilador optimice las actualizaciones.
// list.jsx
import { Show, For } from "solid-js";
<Show when={users().length > 0} fallback={<p>No users yet.</p>}>
<ul>
<For each={users()}>{(user) => <li>{user.name}</li>}</For>
</ul>
</Show>
Show renderiza su contenido de respaldo (fallback) cuando la condición es falsa, y For utiliza claves por referencia para los elementos, permitiéndole mover los nodos del DOM en lugar de recrearlos. Index está disponible cuando prefieres utilizar el índice como clave.
Stores
Para objetos reactivos anidados, createStore proporciona un proxy con actualizaciones basadas en rutas.
// store.jsx
import { createStore } from "solid-js/store";
const [user, setUser] = createStore({
name: "Ada",
address: { city: "London" },
});
setUser("address", "city", "Paris");
Solo las partes del árbol que han cambiado notifican a sus dependientes, por lo que actualizar una propiedad profunda no invalida las lecturas no relacionadas. Los Stores son la forma recomendada de gestionar el estado estructurado.
Recursos y datos asíncronos
createResource envuelve una función asíncrona en una señal, proporcionándote estados de carga y error sin necesidad de llevar un control manual.
// user.jsx
import { createResource, Show } from "solid-js";
const [user] = createResource(() => fetch("/api/user").then((r) => r.json()));
<Show when={user()} fallback={<p>Loading…</p>}>
<h1>{user().name}</h1>
</Show>;
El recurso se vuelve a ejecutar cuando su señal de origen cambia y cancela el trabajo obsoletos, lo que lo convierte en una opción ideal para datos que dependen de parámetros de ruta o de la entrada del usuario.
Enrutamiento y SolidStart
Solid Router se encarga de la navegación en el lado del cliente, y SolidStart es el meta-framework que añade enrutamiento basado en archivos, renderizado en el servidor y carga de datos — el equivalente a Next.js para React o SvelteKit para Svelte. Para cualquier proyecto que sea más que un simple widget, comienza con SolidStart.
Mejores prácticas
- Lee los signals y props donde los utilices; nunca los desestructures una sola vez.
- Usa
createMemopara valores derivados costosos o compartidos ampliamente. - Usa
createEffectúnicamente para efectos secundarios y realiza la limpieza cononCleanup. - Prefiere
createStorepara estados anidados. - Usa
ShowyForen lugar de condicionales manuales y.map. - Mantén los componentes como funciones de configuración y evita depender de la re-ejecución.
- Recurre a
createResourcepara datos asíncronos vinculados a fuentes reactivas.
Errores comunes
- Desestructurar props o valores de signals y romper la reactividad.
- Esperar que el cuerpo del componente se ejecute de nuevo tras un cambio de estado.
- Usar un effect para calcular un valor en lugar de un memo.
- Olvidar
onCleanupy provocar fugas de suscripciones o timers. - Usar
.mapen JSX en lugar deFory perder las actualizaciones basadas en claves (keyed updates). - Asumir que las reglas de React se aplican e intentar usar hooks que no existen.
Próximos pasos
Solid premia la comprensión por encima de la memorización. Compara su modelo con React, Vue y Svelte, refuerza tus conocimientos de JavaScript y TypeScript, y apóyate en Vite para el build. Después, construye una pequeña aplicación reactiva y observa lo poco que se vuelve a ejecutar.