JSX es una extensión de sintaxis similar a XML para JavaScript, desarrollada por el equipo de React para describir declarativamente interfaces de usuario. A diferencia de los motores de plantillas, JSX se compila en llamadas a funciones JavaScript normales, dando todo el poder del lenguaje dentro del marcado. Según React, 2024, JSX es compatible con todos los frameworks y librerías modernas de React.
Puntos clave
JSX (JavaScript XML) es una extensión de sintaxis para JavaScript, presentada por primera vez en React en 2013. Permite a los desarrolladores describir la estructura de una interfaz de usuario en un estilo declarativo, combinando marcado y lógica en un solo archivo.
Antes de JSX, los desarrolladores usaban plantillas de cadenas (Mustache, Handlebars) o creaban elementos DOM manualmente mediante document.createElement. Ambos enfoques tenían desventajas: las plantillas de cadenas no verificaban tipos, y la creación manual de DOM era engorrosa y propensa a errores.
React eligió un camino diferente: incrustar el marcado directamente en el código. Esta decisión generó debate en la comunidad, pero con el tiempo se convirtió en el estándar. Hoy JSX se usa no solo en React, sino también en SolidJS, Preact, Qwik e incluso en Vue a través de plugins.
Un elemento JSX se parece a una etiqueta HTML pero se incrusta directamente en JavaScript. Cada elemento se transpila en una llamada React.createElement con tres argumentos: tipo de elemento, objeto de props e hijos. Un elemento raíz es una regla obligatoria: una expresión JSX debe devolver un elemento padre o un fragmento.
import React from 'react';
// JSX básico: un solo elemento raíz
const element = (
<div className="app">
<h1>Hello, World!</h1>
<p>Welcome to React</p>
</div>
);
Cuando no se necesita un nodo DOM adicional, use React.Fragment o la sintaxis abreviada <></>. Los fragmentos no crean un elemento DOM real, solo agrupan nodos hijos. Esto es especialmente útil en tablas y listas donde un envoltorio adicional rompería la estructura HTML.
function Columns() {
return (
<>
<td>First</td>
<td>Second</td>
</>
);
}
Cualquier expresión de JavaScript se incrusta en JSX mediante llaves { }. Dentro, puede usar variables, llamadas a funciones, operadores ternarios y métodos de arrays. El renderizado condicional se realiza mediante el operador ternario o AND lógico.
function Greeting({ name, isLoggedIn }) {
const items = ['Red', 'Green', 'Blue'];
return (
<div>
{/* Expression with variable */}
<h1>Hello, {name}</h1>
{/* Conditional rendering */}
{isLoggedIn ?
<p>Welcome back!</p :
<button>Login</button>
}
{/* Render array */}
<ul>
{items.map(item =>
<li key={item}>{item}</li>
)}
</ul>
</div>
);
}
Una limitación clave: solo se pueden usar expresiones dentro de las llaves, no instrucciones. No puede usar if/else, for, switch, solo el operador ternario, operadores lógicos y métodos de arrays. Las llamadas a funciones están permitidas, incluidas las funciones flecha.
JSX se parece visualmente a HTML pero tiene diferencias fundamentales. Los atributos se escriben en camelCase: className en lugar de class, onClick en lugar de onclick, tabIndex en lugar de tabindex. Esto se debe a que JSX se transpila a JavaScript, donde los guiones en nombres de propiedades no están permitidos.
| HTML | JSX | Razón |
|---|---|---|
class="wrapper" | className="wrapper" | class es una palabra reservada en JS |
onclick="handle()" | onClick={handle} | camelCase para propiedades JS |
style="color: red" | style={{ color: ‘red’ }} | Objeto de estilos en lugar de cadena |
<input disabled> | <input disabled={true}> | Atributos booleanos explícitos |
Otra diferencia importante: etiquetas autocerrantes. En HTML, algunas etiquetas (br, hr, input) pueden quedar sin cerrar. En JSX, todas las etiquetas autocerrantes deben tener una barra de cierre: <br />, <input />. Los nombres de atributos SVG también se convierten a camelCase: strokeWidth, fillOpacity.
Los navegadores no entienden JSX directamente. Antes de la ejecución, el código JSX pasa por un transpilador: Babel, TypeScript o esbuild. Cada elemento JSX se convierte en una llamada createElement o jsx/runtime.
// JSX original
const element = <h1 className="title">Hello</h1>;
// Después de la transpilación
const element = React.createElement(
'h1',
{ className: 'title' },
'Hello'
);
Con React 17, apareció una nueva transformación JSX que no requiere importar React. La importación automática de jsx-runtime permite escribir componentes sin import React from ‘react’. Babel y TypeScript soportan esta transformación mediante la configuración {"runtime": "automatic"}.
Aunque JSX se asocia con React, otros frameworks también lo usan. SolidJS usa JSX con compilación en nodos DOM reales, sin Virtual DOM. Preact es una alternativa ligera a React con soporte completo de JSX. Vue soporta JSX mediante @vue/babel-plugin-jsx, aunque su plantilla principal es template.
Una diferencia clave son las semánticas de expresiones. En React, las expresiones JSX se ejecutan en cada renderizado. En SolidJS, JSX se compila una vez y las actualizaciones se rastrean mediante señales. Esto afecta el rendimiento: SolidJS no requiere Virtual DOM ni reconciliación, lo que hace que el renderizado JSX sea más rápido.
En TypeScript, JSX es compatible a nivel de lenguaje. Los archivos con extensión .tsx manejan automáticamente la sintaxis JSX. La tipificación de props es una de las principales ventajas de TypeScript + JSX: el IDE sugiere atributos esperados, tipos de callbacks y obligatoriedad de props.
Escriba código JSX que sea fácil de leer y mantener. Extraiga expresiones complejas en variables o funciones separadas: esto mejora la legibilidad y permite probar la lógica por separado del marcado. Use fragmentos en lugar de envoltorios div innecesarios.
La regla de sangría: mantenga la sangría para elementos anidados. Cada nivel de anidamiento es un nivel de sangría. La etiqueta de cierre debe estar al mismo nivel que la etiqueta de apertura. Para atributos largos, use saltos de línea.
Evite funciones flecha en línea en props si se crean en cada renderizado. En tales casos, envuelva el callback en useCallback o mueva la función fuera del componente. Divida componentes complejos en otros más pequeños: cada componente debe manejar una unidad lógica de la interfaz.
Preguntas frecuentes
Sí, mediante el plugin de Babel @babel/plugin-transform-react-jsx, se puede configurar JSX para cualquier librería. SolidJS, Preact, Nerv y otros frameworks usan JSX con su propio runtime. Para total independencia, puede establecer el pragma en su propia función.
class es una palabra reservada en JavaScript. JSX se transpila a createElement, donde el segundo argumento pasa un objeto de props. La propiedad class entra en conflicto con la sintaxis de clases ES6, por lo que React eligió className.
Use plantillas de cadenas o la librería classnames: className={`btn ${isActive ? ‘active’ : ‘’}`}. Para lógica compleja, instale el paquete npm clsx o classnames, que aceptan objetos y arrays.
JSX solo soporta expresiones, no instrucciones. Para condiciones, use el operador ternario, AND lógico (&&) u OR lógico (||). Para lógica compleja, extraiga la condición en una variable o función separada.
El atributo key ayuda a React a identificar elementos de lista durante el rerenderizado. Sin key, React vuelve a renderizar toda la lista al cambiar. Con una key única, React reutiliza nodos DOM y reordena elementos en lugar de recrearlos.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también