JSX
JSX (JavaScript XML) es una extensión de sintaxis de JavaScript que permite escribir elementos similares a HTML directamente en el código JavaScript. Esta sintaxis especial es el núcleo de React y hace que crear interfaces de usuario sea mucho más intuitivo y legible.
¿Qué es JSX exactamente?
JSX no es HTML dentro de JavaScript, aunque lo parezca. En realidad, es azúcar sintáctico que se transforma en llamadas a funciones de JavaScript durante la compilación. Cada elemento JSX se convierte en una llamada a React.createElement()
.
// Esto en JSX:
const elemento = <h1>Hola, mundo!</h1>;
// Se transforma en esto:
const elemento = React.createElement('h1', null, 'Hola, mundo!');
Esta transformación la realiza automáticamente Babel u otros transpiladores, por lo que puedes escribir JSX sin preocuparte por la conversión.
Sintaxis básica de JSX
La sintaxis de JSX combina lo mejor de HTML y JavaScript. Aquí tienes las reglas fundamentales:
1 - Los elementos JSX deben tener un elemento raíz:
// ✅ Correcto - un elemento padre
function MiComponente() {
return (
<div>
<h1>Título</h1>
<p>Contenido</p>
</div>
);
}
// ❌ Incorrecto - múltiples elementos raíz
function MiComponente() {
return (
<h1>Título</h1>
<p>Contenido</p>
);
}
2 - Usar fragmentos cuando no necesites un contenedor:
import { Fragment } from 'react';
function MiComponente() {
return (
<Fragment>
<h1>Título</h1>
<p>Contenido</p>
</Fragment>
);
}
// Sintaxis abreviada
function MiComponente() {
return (
<>
<h1>Título</h1>
<p>Contenido</p>
</>
);
}
3 - Todos los elementos deben cerrarse:
// ✅ Correcto
<input type="text" />
<img src="imagen.jpg" alt="Descripción" />
<br />
// ❌ Incorrecto en JSX
<input type="text">
<img src="imagen.jpg" alt="Descripción">
<br>
Expresiones JavaScript en JSX
Una de las características más útiles de JSX es la capacidad de incrustar expresiones JavaScript usando llaves {}
. Esto permite crear contenido dinámico:
function Saludo() {
const nombre = "Ana";
const edad = 25;
return (
<div>
<h1>Hola, {nombre}!</h1>
<p>Tienes {edad} años</p>
<p>El año que viene tendrás {edad + 1} años</p>
</div>
);
}
Puedes usar cualquier expresión JavaScript válida dentro de las llaves:
function Producto() {
const precio = 29.99;
const descuento = 0.15;
const enOferta = true;
return (
<div>
<h2>Precio: {enOferta ? precio * (1 - descuento) : precio}€</h2>
<p>Estado: {precio > 20 ? "Caro" : "Barato"}</p>
<p>Fecha: {new Date().toLocaleDateString()}</p>
</div>
);
}
Atributos en JSX
Los atributos en JSX funcionan de manera similar a HTML, pero con algunas diferencias importantes:
1 - Usa camelCase para atributos:
// ✅ Correcto en JSX
<div className="contenedor" onClick={manejarClick}>
<label htmlFor="email">Email:</label>
<input type="email" id="email" />
</div>
// ❌ Incorrecto (sintaxis HTML)
<div class="contenedor" onclick="manejarClick()">
<label for="email">Email:</label>
</div>
2 - Atributos dinámicos con expresiones:
function Imagen() {
const rutaImagen = "/imagenes/perfil.jpg";
const textoAlt = "Foto de perfil del usuario";
const esVisible = true;
return (
<img
src={rutaImagen}
alt={textoAlt}
className={esVisible ? "visible" : "oculta"}
width={esVisible ? 200 : 0}
/>
);
}
Renderizado de listas
Para mostrar arrays de datos en JSX, utiliza el método map()
de JavaScript:
function ListaTareas() {
const tareas = [
{ id: 1, texto: "Estudiar React", completada: false },
{ id: 2, texto: "Hacer ejercicio", completada: true },
{ id: 3, texto: "Leer un libro", completada: false }
];
return (
<ul>
{tareas.map(tarea => (
<li key={tarea.id} className={tarea.completada ? "completada" : ""}>
{tarea.texto}
</li>
))}
</ul>
);
}
El atributo key
es fundamental cuando renderizas listas. React lo usa para identificar qué elementos han cambiado, se han añadido o eliminado, optimizando así el rendimiento.
Comentarios en JSX
Los comentarios dentro de JSX requieren una sintaxis especial:
function MiComponente() {
return (
<div>
{/* Este es un comentario en JSX */}
<h1>Título</h1>
{/*
Los comentarios multilínea
también funcionan así
*/}
<p>Contenido</p>
</div>
);
}
Estilos inline en JSX
Los estilos inline en JSX se definen como objetos JavaScript, no como cadenas de texto:
function ComponenteConEstilos() {
const estiloTitulo = {
color: 'blue',
fontSize: '24px',
textAlign: 'center',
marginBottom: '10px'
};
return (
<div>
<h1 style={estiloTitulo}>Título con estilos</h1>
<p style={{ color: 'red', fontWeight: 'bold' }}>
Párrafo con estilos inline
</p>
</div>
);
}
Nota que las propiedades CSS se escriben en camelCase (fontSize
en lugar de font-size
) y los valores numéricos se interpretan automáticamente como píxeles.
Escapado automático
JSX incluye protección automática contra ataques XSS al escapar automáticamente las cadenas de texto:
function ComponenteSeguro() {
const contenidoPeligroso = "<script>alert('XSS')</script>";
return (
<div>
{/* Esto se mostrará como texto, no se ejecutará */}
<p>{contenidoPeligroso}</p>
</div>
);
}
Esta característica hace que JSX sea más seguro por defecto que manipular directamente el DOM con innerHTML
.
Introducción a componentes
Los componentes son la base fundamental de React y representan piezas reutilizables de la interfaz de usuario. Piensa en ellos como bloques de construcción que puedes combinar para crear aplicaciones complejas. Cada componente encapsula su propia lógica, estado y presentación.
En React moderno, trabajamos principalmente con componentes funcionales, que son funciones JavaScript que devuelven JSX. Esta aproximación es más simple, legible y eficiente que las alternativas anteriores.
Tu primer componente funcional
Un componente funcional es simplemente una función JavaScript que devuelve JSX. La convención es usar PascalCase para nombrar componentes (primera letra de cada palabra en mayúscula):
function Bienvenida() {
return <h1>¡Bienvenido a mi aplicación!</h1>;
}
También puedes usar la sintaxis de arrow function:
const Bienvenida = () => {
return <h1>¡Bienvenido a mi aplicación!</h1>;
};
Para usar este componente en otros lugares, simplemente lo invocas como si fuera un elemento HTML:
function App() {
return (
<div>
<Bienvenida />
<p>Este es el contenido principal</p>
</div>
);
}
Componentes con lógica interna
Los componentes pueden contener lógica JavaScript antes del return, lo que permite crear comportamientos dinámicos:
function SaludoPersonalizado() {
const usuario = "María";
const horaActual = new Date().getHours();
let saludo;
if (horaActual < 12) {
saludo = "Buenos días";
} else if (horaActual < 18) {
saludo = "Buenas tardes";
} else {
saludo = "Buenas noches";
}
return (
<div>
<h2>{saludo}, {usuario}!</h2>
<p>Son las {horaActual}:00 horas</p>
</div>
);
}
Esta capacidad de procesar datos y aplicar lógica antes de renderizar es lo que hace a los componentes tan versátiles.
Composición de componentes
Una de las características más importantes de React es la composición de componentes. Puedes crear componentes complejos combinando componentes más simples:
function Perfil() {
return (
<div className="perfil">
<Avatar />
<InfoUsuario />
<ListaHabilidades />
</div>
);
}
function Avatar() {
return (
<img
src="/imagenes/avatar.jpg"
alt="Avatar del usuario"
className="avatar"
/>
);
}
function InfoUsuario() {
return (
<div className="info">
<h3>Juan Pérez</h3>
<p>Desarrollador Frontend</p>
<p>Madrid, España</p>
</div>
);
}
function ListaHabilidades() {
const habilidades = ["React", "JavaScript", "CSS", "HTML"];
return (
<div className="habilidades">
<h4>Habilidades</h4>
<ul>
{habilidades.map(habilidad => (
<li key={habilidad}>{habilidad}</li>
))}
</ul>
</div>
);
}
Esta aproximación hace que el código sea más mantenible y reutilizable, ya que cada componente tiene una responsabilidad específica.
Componentes reutilizables
Los componentes pueden diseñarse para ser reutilizables en diferentes contextos. Por ejemplo, un componente de botón genérico:
function Boton() {
return (
<button className="boton-primario">
Hacer clic
</button>
);
}
// Usar el componente múltiples veces
function Formulario() {
return (
<form>
<input type="text" placeholder="Nombre" />
<input type="email" placeholder="Email" />
<Boton />
<Boton />
</form>
);
}
Organización de componentes en archivos
En aplicaciones reales, cada componente suele estar en su propio archivo. Esta es la estructura típica:
// Archivo: components/Encabezado.jsx
function Encabezado() {
return (
<header>
<h1>Mi Aplicación</h1>
<nav>
<a href="/">Inicio</a>
<a href="/sobre-nosotros">Sobre nosotros</a>
<a href="/contacto">Contacto</a>
</nav>
</header>
);
}
export default Encabezado;
// Archivo: App.jsx
import Encabezado from './components/Encabezado';
function App() {
return (
<div>
<Encabezado />
<main>
<p>Contenido principal de la aplicación</p>
</main>
</div>
);
}
export default App;
Esta separación en archivos mejora la organización del código y facilita el trabajo en equipo.
Convenciones de nomenclatura
Para mantener el código consistente y profesional, sigue estas convenciones:
- Nombres de componentes: PascalCase (
MiComponente
,BarraNavegacion
) - Nombres de archivos: Igual que el componente (
MiComponente.jsx
) - Carpetas de componentes: kebab-case o camelCase (
mi-componente
omiComponente
)
// ✅ Correcto
function PerfilUsuario() {
return <div>Perfil del usuario</div>;
}
// ❌ Incorrecto
function perfilUsuario() {
return <div>Perfil del usuario</div>;
}
// ❌ Incorrecto
function perfil_usuario() {
return <div>Perfil del usuario</div>;
}
Componentes anidados y jerarquía
Los componentes pueden contener otros componentes, creando una jerarquía natural:
function Aplicacion() {
return (
<div className="app">
<EncabezadoPrincipal />
<ContenidoPrincipal />
<PiePagina />
</div>
);
}
function ContenidoPrincipal() {
return (
<main>
<SeccionBienvenida />
<SeccionProductos />
<SeccionTestimonios />
</main>
);
}
function SeccionProductos() {
return (
<section>
<h2>Nuestros Productos</h2>
<TarjetaProducto />
<TarjetaProducto />
<TarjetaProducto />
</section>
);
}
function TarjetaProducto() {
return (
<div className="tarjeta">
<h3>Producto</h3>
<p>Descripción del producto</p>
<span className="precio">€29.99</span>
</div>
);
}
Esta estructura jerárquica refleja la arquitectura natural de las interfaces de usuario y hace que el código sea fácil de entender y mantener.
Componentes con múltiples elementos
Cuando un componente necesita devolver múltiples elementos del mismo nivel, recuerda usar fragmentos o un contenedor:
function ListaContactos() {
return (
<>
<h2>Mis Contactos</h2>
<ContactoIndividual />
<ContactoIndividual />
<ContactoIndividual />
</>
);
}
function ContactoIndividual() {
return (
<div className="contacto">
<img src="/avatar-placeholder.png" alt="Avatar" />
<div>
<h4>Nombre del contacto</h4>
<p>email@ejemplo.com</p>
</div>
</div>
);
}
Los fragmentos (<>...</>
) son especialmente útiles cuando no quieres añadir elementos HTML adicionales al DOM, manteniendo la estructura limpia y semánticamente correcta.
Fuentes y referencias
Documentación oficial y recursos externos para profundizar en React
Documentación oficial de React
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, React es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de React
Explora más contenido relacionado con React y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
- Comprender qué es JSX y cómo se transforma en llamadas a funciones JavaScript.
- Aprender la sintaxis básica y reglas de JSX, incluyendo expresiones, atributos y renderizado de listas.
- Conocer cómo crear y utilizar componentes funcionales en React.
- Entender la composición, reutilización y organización de componentes en archivos.
- Aplicar convenciones de nomenclatura y estructura jerárquica en componentes React.