JSX: La sintaxis de React

En la clase anterior aprendimos a usar React.createElement para crear elementos. Funcionaba, pero el código era verboso y difícil de leer. Ahora vamos a conocer JSX, que hace que React sea mucho más fácil de escribir y entender.

¿Qué es JSX?

JSX (JavaScript XML) es una extensión de sintaxis de JavaScript que nos permite escribir código que parece HTML dentro de JavaScript.

// Con JSX - Parece HTML
const titulo = <h1>¡Hola React!</h1>

// Sin JSX - JavaScript puro
const titulo = React.createElement('h1', null, '¡Hola React!')

¿Por qué JSX?

  • Más legible - Parece HTML, que ya conoces
  • Menos código - Escribes menos para lograr lo mismo
  • Menos errores - Es más fácil ver la estructura
  • Más intuitivo - Se siente natural

💡 Importante: JSX NO es HTML. Es JavaScript que se parece a HTML. Al final se transforma en React.createElement.

Creando nuestro primer archivo con JSX

Vamos a actualizar nuestro archivo react.html para usar JSX:

<!DOCTYPE html>
<html lang="es">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>React con JSX</title>
    <link rel="stylesheet" href="./styles.css" />
  </head>

  <body>
    <!-- Aquí React renderizará nuestra aplicación -->
    <div id="root"></div>

    <!-- 1. Cargar React y ReactDOM desde CDN -->
    <script type="module">
      import React from 'https://esm.sh/react?dev'
      import ReactDOM from 'https://esm.sh/react-dom/client?dev'
      window.React = React
      window.ReactDOMClient = ReactDOM
    </script>

    <!-- 2. ¡NOVEDAD! Cargar Babel para transformar JSX -->
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

    <!-- 3. Nuestro código React CON JSX -->
    <script type="text/babel">
      // Ahora podemos escribir JSX directamente
      const titulo = <h1 style={{ color: '#09f' }}>¡Hola React con JSX!</h1>

      // Renderizar
      window.onload = () => {
        const rootEl = document.querySelector('#root')
        const root = ReactDOMClient.createRoot(rootEl)
        root.render(titulo)
      }
    </script>
  </body>
</html>

¿Qué cambió?

Analicemos los cambios importantes:

1. Añadimos Babel

<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

¿Qué es Babel?

  • Es un transpilador de JavaScript
  • Transforma código moderno (como JSX) a código que el navegador entiende
  • Convierte JSX en llamadas a React.createElement

¿Cómo funciona?

// Escribes esto (JSX)
;<h1>Hola</h1>

// Babel lo transforma a esto (JavaScript)
React.createElement('h1', null, 'Hola')

⚠️ Nota: Usar Babel en el navegador es solo para aprender. En proyectos reales, la transformación se hace al compilar, no en tiempo de ejecución.

2. Cambiamos el tipo de script

<script type="text/babel">
  • En lugar de type="module", usamos type="text/babel"
  • Esto le indica a Babel que debe procesar este código
  • Babel transformará el JSX antes de que se ejecute

Esto es una sintaxis especial de Babel para detectar qué código debe ser transformado por Babel. No es algo nativo de la plataforma y no lo volveremos a ver en el futuro.

3. Escribimos JSX

const titulo = <h1 style={{ color: '#09f' }}>¡Hola React con JSX!</h1>

¡Mira qué diferencia! En lugar de:

const titulo = React.createElement('h1', { style: { color: '#09f' } }, '¡Hola React con JSX!')

Ahora escribimos algo que parece HTML. Mucho más limpio y fácil de leer.

Sintaxis de JSX

Las llaves dobles en style

¿Notaste las dobles llaves en style={{ color: '#09f' }}?

<h1 style={{ color: '#09f' }}>Título</h1>

¿Por qué dos pares de llaves?

  1. Primera llave {} - Indica que vamos a insertar una expresión JavaScript en JSX
  2. Segunda llave {} - Es el objeto JavaScript con los estilos
// Primer par de llaves: "aquí va JavaScript"
<h1 style={...}>

// Segundo par de llaves: objeto con estilos
<h1 style={{ color: '#09f', fontSize: '24px' }}>

Es lo mismo que:

const estilos = { color: '#09f', fontSize: '24px' }
<h1 style={estilos}>Título</h1>

Insertando JavaScript en JSX

Una de las características más poderosas de JSX es que puedes insertar expresiones de JavaScript usando llaves {}:

const nombre = 'Miguel'
const elemento = <h1>Hola, {nombre}</h1>

// Se renderiza: "Hola, Miguel"

Puedes insertar cualquier expresión válida de JavaScript:

<p>La suma de 2 + 2 es: {2 + 2}</p>
// Se renderiza: "La suma de 2 + 2 es: 4"

<p>La fecha es: {new Date().toLocaleDateString()}</p>
// Se renderiza: "La fecha es: 27/10/2025"

<h1>Bienvenido, {usuario.nombre}</h1>
// Accede a propiedades de objetos

<button>Hay {empleos.length} empleos</button>
// Usa métodos de arrays

⚠️ Importante: Solo puedes usar expresiones (cosas que devuelven un valor), no sentencias (if, for, while, etc.).

className en lugar de class

En JSX usamos className en lugar de class:

// ✅ Correcto
<div className="container">Contenido</div>

// ❌ Incorrecto (aunque funciona, no es recomendado)
<div class="container">Contenido</div>

¿Por qué className?

Porque class es una palabra reservada en JavaScript (para definir clases). JSX es JavaScript, así que necesitamos usar className.

Estilos inline en JSX

Los estilos se escriben como objetos JavaScript:

<h1 style={{ color: 'red', fontSize: '24px', marginTop: '10px' }}>Título con estilos</h1>

Diferencias con HTML:

  • camelCase en lugar de kebab-case: fontSize en lugar de font-size
  • Valores en strings si tienen unidades: '24px' en lugar de 24px
  • Objeto JavaScript en lugar de string: {{ color: 'red' }} en lugar de "color: red"
// ❌ CSS tradicional (no funciona en JSX)
<h1 style="color: red; font-size: 24px">Título</h1>

// ✅ JSX
<h1 style={{ color: 'red', fontSize: '24px' }}>Título</h1>

Comparación: Sin JSX vs Con JSX

Veamos un ejemplo real de nuestra app DevJobs:

Sin JSX (verboso y difícil de leer)

const tarjeta = React.createElement(
  'article',
  { className: 'job-listing-card' },
  React.createElement(
    'div',
    null,
    React.createElement('h3', null, 'Desarrollador Frontend'),
    React.createElement('small', null, 'TechCorp | Madrid'),
    React.createElement('p', null, 'Buscamos desarrollador con experiencia en React')
  ),
  React.createElement('button', { className: 'button-apply-job' }, 'Aplicar')
)

Con JSX (limpio y legible)

const tarjeta = (
  <article className="job-listing-card">
    <div>
      <h3>Desarrollador Frontend</h3>
      <small>TechCorp | Madrid</small>
      <p>Buscamos desarrollador con experiencia en React</p>
    </div>
    <button className="button-apply-job">Aplicar</button>
  </article>
)

¡La diferencia es enorme! 🎉

JSX con datos dinámicos

Lo interesante es que podemos combinar JSX con variables:

const empleo = {
  titulo: 'Desarrollador Frontend',
  empresa: 'TechCorp',
  ubicacion: 'Madrid',
  descripcion: 'Buscamos desarrollador con experiencia en React',
}

const tarjeta = (
  <article className="job-listing-card">
    <div>
      <h3>{empleo.titulo}</h3>
      <small>
        {empleo.empresa} | {empleo.ubicacion}
      </small>
      <p>{empleo.descripcion}</p>
    </div>
    <button className="button-apply-job">Aplicar</button>
  </article>
)

Múltiples elementos en JSX

Cuando quieres renderizar varios elementos, debes envolverlos en un elemento padre:

// ✅ Correcto: envueltos en un div
const app = (
  <div>
    <h1>Bienvenido</h1>
    <p>Esta es mi app React</p>
    <button>Empezar</button>
  </div>
)

// ❌ Error: múltiples elementos raíz
const app = (
  <h1>Bienvenido</h1>
  <p>Esta es mi app React</p>
  <button>Empezar</button>
)

🔧 Más adelante aprenderemos sobre React Fragment (<>...</>) que permite agrupar elementos sin crear un div extra en el DOM.

Reglas importantes de JSX

1. Todos los elementos deben cerrarse

// ✅ Correcto
<img src="logo.png" />
<input type="text" />
<br />

// ❌ Incorrecto (en HTML normal sí funciona, pero no en JSX)
<img src="logo.png">
<input type="text">
<br>

2. Un solo elemento raíz

// ✅ Correcto
const app = (
  <div>
    <h1>Título</h1>
    <p>Párrafo</p>
  </div>
)

// ❌ Incorrecto
const app = (
  <h1>Título</h1>
  <p>Párrafo</p>
)

3. Usa paréntesis para JSX multi-línea

// ✅ Bien: con paréntesis
const elemento = (
  <div>
    <h1>Título</h1>
  </div>
)

// ⚠️ También funciona, pero menos legible
const elemento = (
  <div>
    <h1>Título</h1>
  </div>
)

4. JSX es una expresión

Puedes asignar JSX a variables, pasarlo como argumentos, retornarlo de funciones:

// Asignar a variable
const titulo = <h1>Hola</h1>

// Pasar como argumento
root.render(<h1>Hola</h1>)

// Retornar de función (componentes)
function Header() {
  return <h1>Hola</h1>
}

Ejercicio práctico

Actualiza tu archivo react.html y prueba este código:

<script type="text/babel">
  const empleos = [
    { titulo: 'Frontend Developer', empresa: 'TechCorp', ubicacion: 'Madrid' },
    { titulo: 'Backend Developer', empresa: 'CodeLabs', ubicacion: 'Barcelona' },
    { titulo: 'Full Stack Developer', empresa: 'DevStudio', ubicacion: 'Valencia' },
  ]

  const app = (
    <div>
      <h1>DevJobs - Ofertas de empleo</h1>
      <p>Hay {empleos.length} ofertas disponibles</p>

      <article className="job-listing-card">
        <h3>{empleos[0].titulo}</h3>
        <small>
          {empleos[0].empresa} | {empleos[0].ubicacion}
        </small>
        <button className="button-apply-job">Aplicar</button>
      </article>
    </div>
  )

  window.onload = () => {
    const rootEl = document.querySelector('#root')
    const root = ReactDOMClient.createRoot(rootEl)
    root.render(app)
  }
</script>

Lo que hemos aprendido

En esta clase has aprendido:

  • 🎯 Qué es JSX y por qué hace React más fácil
  • 🔧 Cómo usar Babel para transformar JSX a JavaScript
  • 📝 Sintaxis de JSX - llaves, className, style, etc.
  • 💻 Insertar JavaScript en JSX con {}
  • 📦 Reglas de JSX - cerrar tags, un elemento raíz, etc.
  • Diferencias con HTML - className vs class, estilos como objetos, etc.

En la siguiente clase aprenderemos sobre componentes, que es donde JSX realmente brilla. Veremos cómo crear funciones que retornan JSX y reutilizarlas en toda la aplicación.

💡 Recuerda: JSX es opcional, pero el 99.9% de proyectos React lo usan porque hace el código mucho más legible y mantenible.