← React & TypeScript

Fundamentos de React

¿Qué es JSX y en qué se diferencia de HTML?

Ver respuesta — intenta responderla en voz alta primero

JSX es una extensión de sintaxis de JavaScript que te deja escribir marcado parecido a HTML dentro de tu código. No es HTML: es azúcar sintáctica que el compilador transforma en llamadas a funciones de React (como createElement o el runtime de JSX), es decir, en objetos de JavaScript.

Cuando escribes <h1>Hola</h1> en un componente, el navegador nunca ve eso. Una herramienta de compilación (Babel, SWC, el compilador de TypeScript...) lo transforma en una llamada de función que devuelve un objeto describiendo ese elemento. React usa esos objetos para saber qué renderizar.

Puntos clave que conviene tener claros:

  • Es JavaScript, no HTML: por eso puedes guardarlo en variables, devolverlo desde funciones o pasarlo como argumento.
  • Expresiones con llaves {}: dentro de las llaves puedes poner cualquier expresión de JavaScript (variables, ternarios, llamadas a funciones). No puedes poner sentencias como if o for directamente.
  • Atributos con nombres de JavaScript: como class y for son palabras reservadas, JSX usa className y htmlFor. Los atributos van en camelCase (onClick, tabIndex).
  • Un solo elemento raíz: una expresión JSX debe devolver un único nodo. Si necesitas varios hermanos sin envolverlos en un <div>, usas un Fragment (<>...</>).
// Esto que escribes...
const saludo = <h1 className="titulo">Hola, Mike</h1>;

// ...se compila a algo equivalente a esto (runtime clásico):
// const saludo = React.createElement("h1", { className: "titulo" }, "Hola, Mike");
// Es decir: JSX produce objetos de JavaScript, no HTML.

type Props = { nombre: string; esAdmin: boolean };

function TarjetaUsuario({ nombre, esAdmin }: Props) {
  // Fragment (<>...</>) para devolver varios hermanos sin un div extra
  return (
    <>
      {/* Las llaves evalúan expresiones de JavaScript */}
      <h2>{nombre.toUpperCase()}</h2>
      <p>Rol: {esAdmin ? "Administradora" : "Usuaria"}</p>
      {/* htmlFor en lugar de for, className en lugar de class */}
      <label htmlFor="correo" className="etiqueta">Correo</label>
      <input id="correo" type="email" />
    </>
  );
}

// <TarjetaUsuario nombre="Ana" esAdmin={true} /> renderiza:
// ANA / Rol: Administradora / y el campo de correo con su label.

Intentar devolver varios elementos raíz o usar atributos de HTML tal cual:

// MAL: dos elementos raíz y atributo `class`
function Perfil() {
  return (
    <h1 class="titulo">Perfil</h1>
    <p>Bienvenida</p>
  ); // Error de compilación: JSX debe tener un solo elemento raíz
}

// BIEN: Fragment como raíz y className en lugar de class
function PerfilCorregido() {
  return (
    <>
      <h1 className="titulo">Perfil</h1>
      <p>Bienvenida</p>
    </>
  );
}

"JSX es una extensión de sintaxis que me permite describir la UI con algo parecido a HTML, pero dentro de JavaScript. En realidad es azúcar sintáctica: el compilador lo convierte en llamadas a funciones de React que devuelven objetos. Por eso hay diferencias con HTML, como usar className en lugar de class o htmlFor en lugar de for. Dentro de llaves puedo evaluar cualquier expresión de JavaScript, y cada bloque JSX debe tener un solo elemento raíz; si necesito varios hermanos, uso un Fragment para no meter divs innecesarios."

Reto rápido

Corrige este componente para que compile y funcione (tiene tres errores relacionados con JSX):

function Formulario() {
  const titulo = "Registro";
  return (
    <label for="nombre">titulo</label>
    <input id="nombre" class="campo" />
  );
}
Ver solución
function Formulario() {
  const titulo = "Registro";
  return (
    // 1. Fragment: JSX necesita un solo elemento raíz.
    // 2. htmlFor y llaves para evaluar la variable. 3. className.
    <>
      <label htmlFor="nombre">{titulo}</label>
      <input id="nombre" className="campo" />
    </>
  );
}