Construimos la Misma App en SolidJS y React: Signals vs Hooks
El trimestre pasado, teníamos un proyecto de cliente que nos dio la excusa perfecta para hacer algo que estábamos ansiosos por intentar: construir la misma aplicación tanto en SolidJS como en React, y luego comparar todo. No una app de tareas. No un contador. Un dashboard de producción real con autenticación, actualizaciones de datos en tiempo real, formularios complejos y un módulo de gráficos que renderiza miles de puntos de datos.
Los resultados nos sorprendieron. No porque un framework "ganara" -- sino porque los tradeoffs eran mucho más matizados de lo que sugiere el discurso de Twitter. Algunas cosas las esperábamos. Algunas cosas nos sorprendieron completamente. Esto es lo que realmente aprendimos.
Tabla de Contenidos
- La App que Construimos
- Signals vs Hooks: Un Cambio de Modelo Mental
- Comparación de Tamaño de Bundle
- Benchmarks de Rendimiento de Renderizado
- Experiencia del Desarrollador y Ecosistema
- Tradeoffs de Producción que Realmente Importan
- Cuándo Elegir SolidJS sobre React
- Comparación de Código: Patrones Reales
- FAQ

La App que Construimos
La aplicación es un dashboard de análisis en tiempo real para un cliente de e-commerce. Aquí está lo que incluye:
- Flujo de autenticación con tokens JWT y lógica de refresh
- Dashboard con 6 paneles de widgets, cada uno obteniendo datos de diferentes endpoints de API
- Feed de órdenes en tiempo real usando conexiones WebSocket
- Gráficos interactivos renderizando 5,000+ puntos de datos (usando una librería de gráficos)
- Formularios de filtro complejos con dropdowns dependientes y selectores de rango de fechas
- Panel de configuración de administrador con gestión de estado anidado
- Layout responsivo con navegación de barra lateral
Ambas versiones se conectan a la misma API backend. Ambas usan TypeScript. Ambas usan Vite como herramienta de build. Mantuvimos las dependencias de terceros lo más similares posible -- misma librería de gráficos (Chart.js), mismo cliente HTTP (ky), mismo wrapper de WebSocket.
La versión de React usa React 19 con hooks. La versión de SolidJS usa Solid 1.9. No usamos meta-frameworks (sin Next.js, sin SolidStart) porque queríamos aislar las diferencias del framework sin que routing y SSR enturbiaran la comparación.
Signals vs Hooks: Un Cambio de Modelo Mental
Este es el grande. Y honestamente, le tomó a nuestro equipo alrededor de una semana dejar de escribir código con forma de React en SolidJS.
Cómo Funcionan los React Hooks
Tú ya sabes esto, pero vale la pena establecerlo explícitamente para la comparación. El modelo de React es: cuando el estado cambia, la función del componente se re-ejecuta. Toda la función. Cada useState, cada useMemo, cada useCallback -- todos son mecanismos para trabajar alrededor del hecho de que la función completa se re-ejecuta.
// React: Esta función completa se re-ejecuta en cada cambio de estado
function OrderFeed() {
const [orders, setOrders] = useState([]);
const [filter, setFilter] = useState('all');
// Esto se recalcula en cada renderizado a menos que lo memoicemos
const filteredOrders = useMemo(() =>
orders.filter(o => filter === 'all' || o.status === filter),
[orders, filter]
);
// Esta ref se recrea conceptualmente en cada renderizado
const handleNewOrder = useCallback((order) => {
setOrders(prev => [order, ...prev]);
}, []);
useEffect(() => {
const ws = connectWebSocket(handleNewOrder);
return () => ws.close();
}, [handleNewOrder]);
return <OrderList orders={filteredOrders} />;
}
Cómo Funcionan los Solid Signals
El modelo de Solid es fundamentalmente diferente. La función del componente se ejecuta una sola vez. Después de eso, solo las expresiones específicas que leen un signal se re-ejecutan cuando ese signal cambia. No hay virtual DOM diff. No hay reconciliación. El grafo reactivo rastrea exactamente qué nodos del DOM dependen de qué signals.
// Solid: Esta función se ejecuta UNA SOLA VEZ
function OrderFeed() {
const [orders, setOrders] = createSignal([]);
const [filter, setFilter] = createSignal('all');
// Esto se rastrea automáticamente -- no se necesita array de dependencias
const filteredOrders = createMemo(() =>
orders().filter(o => filter() === 'all' || o.status === filter())
);
// No se necesita useCallback -- este closure es estable
const handleNewOrder = (order) => {
setOrders(prev => [order, ...prev]);
};
// onMount en lugar de useEffect con deps vacías
onMount(() => {
const ws = connectWebSocket(handleNewOrder);
onCleanup(() => ws.close());
});
return <OrderList orders={filteredOrders()} />;
}
Qué Significa Esto en la Práctica
La versión de Solid no tiene arrays de dependencias. Sin useCallback. Sin useMemo para estado derivado (aunque createMemo existe para cálculos costosos -- la diferencia es que es opt-in para rendimiento, no requerido para corrección).
Aquí está lo que realmente nos mordió durante el desarrollo:
La destructuración de props mata la reactividad en Solid. Teníamos un desarrollador junior destructurando props en un componente Solid y pasamos 45 minutos debugueando por qué las actualizaciones no se propagaban. En React, la destructuración está bien porque la función completa se re-ejecuta. En Solid, necesitas acceder a
props.valuedentro del JSX o un scope rastreado.Los early returns son complicados en Solid. No puedes hacer
if (!data()) return <Loading />al inicio de un componente Solid de la manera que lo harías en React. La función del componente solo se ejecuta una vez, así que ese condicional nunca se re-evaluaría. Necesitas<Show when={data()}>en su lugar.Sin bugs de closure obsoleto. Este fue el gran ganador. En nuestra versión de React, tuvimos tres bugs de closure obsoleto separados en la primera semana relacionados con handlers de WebSocket capturando estado antiguo. La versión de Solid tuvo cero, porque los signals siempre se leen en el momento del acceso, no capturados en un closure.
Comparación de Tamaño de Bundle
Medimos ambas compilaciones de producción con la misma configuración de Vite, compresión gzip y estrategia de code splitting.
| Métrica | React 19 | SolidJS 1.9 | Diferencia |
|---|---|---|---|
| Runtime del framework | 44.2 KB (gzip) | 7.1 KB (gzip) | -84% |
| Bundle inicial total | 127.8 KB | 89.3 KB | -30% |
| App total (todos los chunks) | 312.4 KB | 274.1 KB | -12% |
| Primer chunk (ruta crítica) | 68.4 KB | 41.2 KB | -40% |
| Número de chunks | 14 | 14 | Igual |
El runtime de Solid es dramáticamente más pequeño. Eso no es novedad -- Ryan Carniato ha hablado extensamente sobre esto. Pero lo que nos sorprendió fue que la diferencia de tamaño total de la app se redujo significativamente una vez que agregaste código de aplicación real, librerías de terceros y assets.
El runtime del framework importa más para la carga inicial. Y a 7.1 KB gzipped, Solid básicamente desaparece en el ruido. Los 44 KB de React son notables, especialmente en conexiones móviles.
Tree Shaking
Solid hace tree-shaking mejor que React. Las primitivas de Solid no utilizadas se eliminan completamente. Con React, el reconciliador y la arquitectura fiber se envían sin importar si usas todas sus características o no. Confirmamos esto construyendo una página mínima en ambos -- el piso de Solid es más bajo.

Benchmarks de Rendimiento de Renderizado
Ejecutamos benchmarks estructurados usando perfiles de rendimiento de Chrome DevTools, Lighthouse e instrumentación de timing personalizada. Todas las pruebas en un MacBook Pro M2 con throttling de CPU establecido a 4x slowdown para simular dispositivos de rango medio.
Renderizado de Gráficos (5,000 puntos de datos)
| Métrica | React 19 | SolidJS 1.9 |
|---|---|---|
| Renderizado inicial | 142ms | 89ms |
| Re-renderizado en cambio de filtro | 67ms | 23ms |
| Memoria durante renderizado | 18.4 MB | 11.2 MB |
| Nodos del DOM creados | 5,847 | 5,812 |
Solid fue consistentemente más rápido en re-renderizados porque no difiere un árbol virtual del DOM. Cuando un signal de filtro cambia, solo las expresiones que leen ese signal se actualizan. Las mejoras del compilador de React 19 ayudaron -- la misma prueba en React 18 fue 95ms para re-renderizados -- pero Solid seguía teniendo una ventaja clara.
Feed de Órdenes en Tiempo Real (100 actualizaciones/segundo)
Esto es donde las cosas se pusieron realmente interesantes. Empujamos 100 mensajes de WebSocket por segundo al feed de órdenes.
| Métrica | React 19 | SolidJS 1.9 |
|---|---|---|
| Caídas de fotogramas (por 10s) | 12 | 2 |
| Tiempo de paint promedio | 8.3ms | 3.1ms |
| Tiempo de paint máximo | 34ms | 11ms |
| Uso de CPU (promedio) | 24% | 9% |
Solid absolutamente aplastó este benchmark. Las actualizaciones de alta frecuencia son donde la reactividad fine-grained paga los mayores dividendos. React estaba batching de actualizaciones (lo cual es bueno), pero aún estaba difiriendo más DOM del necesario en cada batch.
Deberíamos notar: el useTransition de React 19 y el batching automático hicieron esto mucho mejor que lo que habría sido React 18. Y para la mayoría de las apps del mundo real, no estás empujando 100 actualizaciones por segundo. A 10 actualizaciones/segundo, ambos frameworks eran suave.
Formulario Complejo con 40 Campos
| Métrica | React 19 | SolidJS 1.9 |
|---|---|---|
| Lag de entrada de keystroke | 2-4ms | <1ms |
| Renderizado de envío de formulario | 28ms | 12ms |
| Re-renderizados de componentes por keystroke | 3-8 | 1 |
En React, escribir en un campo causaría que los componentes padres se re-renderizaran a menos que memoizáramos todo cuidadosamente. En Solid, escribir en un campo literalmente solo actualiza ese nodo de texto del DOM de ese campo. Nada más se re-ejecuta.
Experiencia del Desarrollador y Ecosistema
El rendimiento no es todo. Realmente tienes que construir la cosa, debuguearla, contratar para ella y mantenerla.
Tamaño del Ecosistema (a principios de 2025)
| Factor | React | SolidJS |
|---|---|---|
| Descargas semanales en npm | ~28M | ~85K |
| Estrellas en GitHub | 233K+ | 33K+ |
| Preguntas en Stack Overflow | 470K+ | ~2K |
| Librerías de componentes UI | 50+ opciones maduras | 5-8 opciones |
| Publicaciones de empleos (LinkedIn US) | ~45,000 | ~200 |
| Meta-framework | Next.js (maduro) | SolidStart (beta) |
Este es el elefante en la sala. El ecosistema de React es órdenes de magnitud más grande. Cuando necesitábamos un date range picker para Solid, tuvimos que portar uno de React o escribir el nuestro. En React, teníamos 15 opciones para elegir.
Usamos Kobalte para primitivos de UI accesibles en Solid, y es genuinamente bueno. Pero no es Radix UI en términos de cobertura de componentes.
Debugging
React DevTools es maduro, bien mantenido, y algo que cada desarrollador frontend conoce. Solid tiene su propia extensión de DevTools, y es decente -- puedes inspeccionar el grafo de signal, que es realmente más útil para rastrear bugs de reactividad que la vista del árbol de componentes de React. Pero es menos pulido.
Soporte de TypeScript
Ambos son excelentes. El soporte de TypeScript de Solid es realmente ligeramente mejor para JSX porque el compilador maneja más en tiempo de compilación. Tuvimos menos acrobacias de tipo en la base de código de Solid.
Tradeoffs de Producción que Realmente Importan
Después de construir ambas versiones e implementar la versión de Solid en staging (el cliente finalmente eligió React para producción -- más sobre esto abajo), aquí están los tradeoffs que realmente importaban:
Contratación
Nuestro cliente tiene un equipo de 8 desarrolladores frontend. Todos conocen React. Ninguno había usado Solid. Estimación de tiempo de entrenamiento: 2-3 semanas para profesionalidad, 2-3 meses para maestría. Ese es un costo real. Este es el factor más grande en la mayoría de decisiones de producción, y es por qué típicamente recomendamos React o frameworks como Next.js para equipos que necesitan contratar frecuentemente.
Compatibilidad de Librerías de Terceros
Tuvimos que escribir wrappers personalizados para tres librerías que tenían integraciones específicas de React. Esto agregó aproximadamente 20 horas de tiempo de desarrollo. En un proyecto de React, esas horas no existen.
Renderizado del Lado del Servidor
SolidStart es prometedor pero seguía siendo beta durante nuestro proyecto. Next.js es battle-tested. Para proyectos donde necesitamos SSR de nivel de producción con todos los adornos, seguimos alcanzando Next.js development o Astro dependiendo del modelo de contenido.
Rendimiento Donde Importa
Aquí está la verdad honesta: para este dashboard en particular, ambos frameworks funcionaron lo suficientemente bien para producción. La versión de Solid fue mediblemente más rápida, pero la versión de React nunca fue lenta. Los usuarios no notarían la diferencia en la mayoría de interacciones.
La excepción fue el feed en tiempo real a altas frecuencias de actualización. Si tu app tiene un caso de uso como ese, la ventaja de rendimiento de Solid es significativa, no solo alardear de benchmark.
Cuándo Elegir SolidJS sobre React
Después de este experimento, aquí está nuestro framework honesto para la decisión:
Elige SolidJS cuando:
- Tu app tiene actualizaciones reactivas de alta frecuencia (dashboards, plataformas de trading, colaboración en tiempo real)
- El tamaño del bundle es crítico (widgets embebidos, micro-frontends, mobile-first)
- Tu equipo es pequeño y está dispuesto a invertir en aprender un nuevo paradigma
- Quieres reactividad fine-grained sin pelear contra el framework
- Estás construyendo algo nuevo y no necesitas un ecosistema de librería de componentes masivo
Elige React cuando:
- Tu equipo ya conoce React (esto solo generalmente es decisivo)
- Necesitas un meta-framework maduro (Next.js, Remix)
- La disponibilidad de librerías de terceros es importante
- Estás contratando y necesitas un gran pool de talento
- Los requerimientos de rendimiento de tu app son típicos (no extremos)
Para nuestros proyectos de headless CMS development, React aún domina porque las integraciones de CMS (Sanity, Contentful, Storyblok) tienen SDKs de React de primera clase. El soporte de Solid existe pero a menudo es mantenido por la comunidad.
Comparación de Código: Patrones Reales
Veamos algunos patrones reales del proyecto lado a lado.
Data Fetching con Estados de Carga
React:
function Dashboard() {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchDashboardData()
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
}, []);
if (loading) return <Skeleton />;
if (error) return <ErrorBanner error={error} />;
return <DashboardGrid data={data} />;
}
SolidJS:
function Dashboard() {
const [data] = createResource(fetchDashboardData);
return (
<Suspense fallback={<Skeleton />}>
<ErrorBoundary fallback={(err) => <ErrorBanner error={err} />}>
<DashboardGrid data={data()} />
</ErrorBoundary>
</Suspense>
);
}
El createResource de Solid con Suspense es genuinamente elegante. React también tiene Suspense (y ha mejorado en React 19), pero la versión de Solid se sintió más natural trabajar. Menos boilerplate, menos variables de estado que gestionar.
Renderizado Condicional
React:
{user ? (
<Profile user={user} />
) : (
<LoginPrompt />
)}
SolidJS:
<Show when={user()} fallback={<LoginPrompt />}>
{(u) => <Profile user={u()} />}
</Show>
El componente <Show> de Solid existe porque los ternarios no funcionan igual cuando la función del componente solo se ejecuta una vez. Tomó acostumbrarse, pero el patrón de callback te da una referencia estrecha y no-null que es buena para TypeScript.
Renderizado de Listas
React:
{orders.map(order => (
<OrderRow key={order.id} order={order} />
))}
SolidJS:
<For each={orders()}>
{(order) => <OrderRow order={order} />}
</For>
El <For> de Solid no necesita keys porque rastrea items del array por referencia. Cuando un item se mueve en el array, Solid mueve el nodo del DOM real. React desmontaría y remontaría. Por eso el rendimiento de lista de Solid es tan bueno.
FAQ
¿Es SolidJS production-ready en 2025?
Sí. Solid 1.x ha sido estable por más de dos años. Compañías como Cloudflare y Samsung lo han usado en producción. La librería principal es madura y bien testeada. El ecosistema alrededor (SolidStart, librerías de componentes) es más pequeño que el de React pero está creciendo constantemente. La pregunta no es si Solid está listo -- es si los requerimientos de tu equipo y proyecto se alinean con el tamaño de su ecosistema.
¿Puedo migrar de React a SolidJS incrementalmente?
No fácilmente. A pesar de la sintaxis JSX similar, los modelos de runtime son fundamentalmente diferentes. No puedes incrustar componentes de Solid dentro de una app de React (o vice versa) sin límites de iframe o web component. Una migración sería esencialmente una reescritura. Si estás considerándolo, comienza con una característica nueva aislada o micro-frontend en lugar de intentar convertir código de React existente.
¿SolidJS soporta renderizado del lado del servidor?
Sí. SolidStart proporciona SSR, streaming y server functions. Es funcional y mejora rápidamente, pero a principios de 2025, aún es menos maduro que Next.js o Remix. Para proyectos SSR-heavy, seguiríamos recomendando evaluar Next.js o Astro dependiendo de tus necesidades de contenido.
¿Cómo se compara el compilador de React 19 con el enfoque de Solid?
El compilador de React 19 (anteriormente React Forget) auto-memoiza componentes para reducir re-renderizados innecesarios. Es una mejora significativa. Pero seguirá funcionando dentro del modelo de React de re-ejecutar funciones de componentes y difundir un virtual DOM. Solid salta ambos pasos completamente. El compilador hace React más rápido, pero no cambia la arquitectura fundamental. En nuestros benchmarks, React 19 con el compilador fue aproximadamente 30% más rápido que React 18, pero aún más lento que Solid en escenarios update-heavy.
¿Qué hay de Preact Signals como un punto medio?
Preact Signals (y el adaptador @preact/signals-react) traen reactividad similar a signals al ecosistema de React. Es un enfoque interesante, pero está peleando contra el modelo central de React en lugar de trabajar con él. Lo probamos brevemente y encontramos casos extremos con Suspense y características concurrentes. Si quieres signals, Solid te da la experiencia completa sin la desajuste de impedancia.
¿Es SolidJS más difícil de aprender que React?
Si ya conoces React, la API de Solid se verá familiar -- JSX similar, patrones similares. La parte difícil es desaprender el modelo mental de React. Alcanzarás patrones de useEffect que no existen. Destructurarás props y romperás la reactividad. Intentarás early returns y te preguntarás por qué no funcionan. Presupuesto alrededor de 1-2 semanas para que un dev de React experimentado sea productivo en Solid, y otros 1-2 meses para dejar de escribir Solid con sabor a React.
¿Qué framework tiene mejor soporte de TypeScript?
Ambos tienen excelente soporte de TypeScript. Solid tiene una ligera ventaja porque su compilador puede proporcionar tipos más estrechos en ciertos patrones (como el callback en <Show>), y no necesitas el mismo volumen de parámetros de tipo genérico que los hooks de React complejos a veces requieren. Pero honestamente, ambos son excelentes. Esto no debería ser un factor decisivo.
¿Debería usar SolidJS para mi próximo proyecto?
Depende de tus restricciones. Si eres un equipo pequeño construyendo algo sensible al rendimiento y estás dispuesto a invertir en curva de aprendizaje y trabajar alrededor de un ecosistema más pequeño, Solid es genuinamente una opción excelente. Si necesitas contratar desarrolladores de React, usar librerías de componentes establecidas, o necesitas un meta-framework battle-tested para producción, React es la apuesta más segura. No hay una respuesta universal -- solo la respuesta correcta para tu situación específica. Si quieres hablar sobre la decisión para tu proyecto, contáctanos y podemos ayudarte a evaluar los tradeoffs.