Saltar al contenido

Diferencias con el JSX de React

Los desajustes concretos que tropiezan a quien llega de React: class en vez de className, for en vez de htmlFor, el objeto style con nombres CSS y unidades explícitas, la ausencia de keys, y los refs como variables asignadas o callbacks en lugar de useRef y .current.

Atributos que vuelven al HTML

React inventó className y htmlFor porque class y for son palabras reservadas de JavaScript, y sus elementos son objetos cuyas propiedades chocaban con ellas. Solid no fabrica objetos: escribe atributos sobre nodos reales, así que recupera los nombres del HTML de toda la vida.

JSX
// React                          // Solid<div className="card" />          <div class="card" /><label htmlFor="email" />         <label for="email" />

Para clases condicionales, React te obliga a concatenar cadenas o a tirar de librerías. Solid ofrece dos herramientas nativas: el atributo classList, que recibe un objeto de clase a booleano, y el namespace class: para una sola clase. Ambos actualizan cada clase de forma independiente y reactiva.

JSX
// objeto: cada clave se activa segun su booleano<button classList={{ activo: seleccionado(), grande: esGrande() }} />// namespace: una unica clase, mismo efecto<button class:activo={seleccionado()} />

Solid tolera className y htmlFor como alias por compatibilidad, pero conviene leerlos como una señal de que aún piensas en React: lo idiomático es class y for. Esa misma vuelta al HTML rige para los atributos de SVG y para los data-* y aria-*, que se escriben literalmente, sin recamelizar.

El objeto style: nombres CSS y unidades

Aquí está el desajuste que más silenciosamente rompe cosas. En React el objeto de estilos usa camelCase y añade px por ti: {{ backgroundColor: "red", fontSize: 16 }}. En Solid el objeto de estilos habla CSS literal: las claves son propiedades CSS en kebab-case y los valores llevan unidad explícita, porque Solid las asigna tal cual sin interpretarlas.

JSX
// React<p style={{ backgroundColor: "red", fontSize: 16 }} />// Solid: nombres CSS y unidades a mano<p style={{ "background-color": "red", "font-size": "16px" }} />

Olvidar el px es el error clásico: fontSize: 16 en Solid no hace nada, porque font-size: 16 no es CSS válido. A cambio, este objeto acepta cosas que el de React no maneja con naturalidad, como variables CSS personalizadas, y admite el namespace style: para una propiedad suelta.

JSX
// variables CSS y propiedad individual reactiva<div style={{ "--acento": color() }} /><div style:width={`${ancho()}px`} />

El objeto no es la única forma: style acepta también una cadena CSS completa —útil cuando el estilo llega ya serializado desde otra fuente—, aunque con cadena Solid reemplaza el bloque entero en cada cambio mientras que con objeto actualiza cada propiedad por separado. Prefiere el objeto siempre que puedas.

No hay keys: la lista se reconcilia por referencia

En React, key es la pista que orienta al reconciliador para emparejar elementos entre renders. Solid no reconcilia listas comparando árboles, así que la prop key no existe en su JSX. En su lugar tienes dos componentes de control de flujo con estrategias opuestas.

JSX
// el hijo es una funcion; recibe el item (como signal en For)<For each={usuarios()}>  {(u) => <li>{u.nombre}</li>}</For>

Con <Index> el patrón se invierte: el hijo recibe una señal, porque lo que persiste es la posición y lo que varía es el contenido de esa fila.

JSX
// en Index el item llega como signal: color() lee el valor de la fila<Index each={colores()}>  {(color, i) => <li>{i + 1}: {color()}</li>}</Index>

La ausencia de key desconcierta al principio, pero es coherente: no le das una pista a un algoritmo de diffing porque no hay tal algoritmo. Eliges la semántica —identidad o posición— seleccionando el componente, y Solid mueve o parchea nodos en consecuencia.

Refs: variables y callbacks, sin .current

React captura nodos con useRef y accede a ellos por .current, un objeto mutable que sobrevive a los renders. Solid, como el componente corre una vez, no necesita ese envoltorio: ref acepta directamente una variable que el compilador asigna, o una función callback que recibe el nodo.

JSX
function Campo() {  let entrada;                       // variable local, sin useRef  onMount(() => entrada.focus());    // ya apunta al nodo real  return <input ref={entrada} type="text" />;}

La forma variable es azúcar del compilador: ref={entrada} se traduce en entrada = elNodo en el momento de crearlo. La forma callback es más flexible y sirve cuando necesitas lógica en el instante de la conexión, o para reenviar la referencia hacia arriba.

JSX
// callback: se invoca con el nodo al montarse<input ref={(el) => configurar(el)} />

Reenviar una referencia a través de un componente hijo no necesita API especial: el hijo recibe ref como una prop más y se la entrega a su nodo. Como ref admite tanto variable como función, el padre puede pasar cualquiera de las dos y el hijo la propaga sin enterarse de cuál es.

JSX
function Campo(props) {  return <input ref={props.ref} />;   // reenvia la referencia del padre}// el padre captura el input como si fuera suyolet entrada;<Campo ref={entrada} />;