Tienes el proyecto de CicloUrbano creado y funcionando, pero todo lo que ves en pantalla es la plantilla de ejemplo de Vite. Es hora de borrarla y escribir el primer código verdaderamente tuyo. En esta lección desmontarás pieza a pieza el mecanismo que hace que React aparezca en la página, entenderás la relación exacta entre index.html y src/main.jsx, y crearás tus dos primeros componentes: Bienvenida y TarjetaBicicleta. Al terminar sabrás qué es un componente, cómo se escribe, cómo se usa y por qué su nombre debe empezar obligatoriamente por mayúscula.
Contenido
- Limpiar la plantilla de ejemplo
- Anatomía de
index.html: el punto de anclaje src/main.jsxlínea a línea- Tu primer componente:
Bienvenida - Un componente es una función que devuelve JSX
- La convención de la mayúscula inicial
- Segundo componente:
TarjetaBicicleta React.StrictMode: qué es y por qué ves cosas dos veces- Ver el cambio en caliente
- Limpiar la plantilla de ejemplo
Vite genera una demostración con un contador y logotipos. Es útil para comprobar que todo funciona, pero estorba para empezar. Con el servidor de desarrollo corriendo (npm run dev), haz esta limpieza.
Borra estos ficheros, que no vamos a necesitar:
Vacía src/index.css y déjalo con unos estilos base sobrios para CicloUrbano:
/* src/index.css — estilos globales de CicloUrbano */
:root {
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
line-height: 1.6;
color: #1f2933;
background-color: #f5f7fa;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 2rem;
}
h1,
h2,
h3 {
line-height: 1.25;
margin-top: 0;
}Sustituye por completo el contenido de src/App.jsx:
// src/App.jsx
function App() {
return (
<main>
<h1>CicloUrbano</h1>
</main>
);
}
export default App;Guarda y mira el navegador: la demostración ha desaparecido y queda un título. Si ves un error en pantalla o en la consola, casi seguro es porque App.jsx sigue importando ./App.css o ./assets/react.svg, ficheros que acabas de borrar. Revisa que no quede ningún import sobrante.
Este App.jsx mínimo ya contiene todos los conceptos de la lección: una función llamada App, que devuelve algo que parece HTML, y que se exporta. Vamos a entender cada parte.
- Anatomía de
index.html: el punto de anclaje
index.html: el punto de anclajeRecuerda el HTML del proyecto, ya con el título de CicloUrbano:
<!doctype html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CicloUrbano — Alquiler de bicicletas urbanas</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>Esto es lo que ocurre cuando alguien abre la página:
- El navegador descarga este HTML. El
<body>contiene un únicodivvacío. En ese momento la página está literalmente en blanco. - Encuentra la etiqueta
<script type="module">y descarga/src/main.jsx(en desarrollo lo sirve Vite ya transformado; en producción será el paquete generado pornpm run build). - Ese script ejecuta React, que crea los nodos del DOM y los inserta dentro de
div#root. - La página aparece.
De ahí viene el nombre de SPA (Single Page Application): existe una sola página HTML real y todo el contenido lo genera JavaScript dentro de un contenedor. El id="root" no es mágico: podría llamarse app o ciclourbano siempre que main.jsx lo busque con el mismo nombre. root es la convención universal, así que consérvala.
sequenceDiagram
participant N as Navegador
participant H as index.html
participant M as main.jsx
participant R as React
N->>H: Solicita la página
H-->>N: HTML con div#root vacío
N->>M: Carga el módulo /src/main.jsx
M->>R: createRoot(div#root)
R->>R: Ejecuta el componente App
R-->>N: Inserta los nodos dentro de div#root
src/main.jsx línea a línea
src/main.jsx línea a líneaEste es el fichero completo:
// src/main.jsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';
import App from './App.jsx';
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>
);Cinco líneas de importación y una sentencia. Vamos una por una.
import { StrictMode } from 'react';
Del paquete react importamos StrictMode, un componente especial de ayuda al desarrollo. Lo veremos en el apartado 8.
import { createRoot } from 'react-dom/client';
Aquí está la separación de responsabilidades que mencionamos en la lección 01-01: react sabe describir interfaces; react-dom sabe pintarlas en un navegador. El subcamino /client indica que es el renderizador de cliente (existe también react-dom/server para renderizado en servidor, tema del Módulo 10).
createRoot crea una raíz de React: la conexión entre un nodo del DOM real y el árbol de componentes que React va a gestionar dentro de él.
Importante:
createRootes la API moderna, introducida en React 18. En tutoriales antiguos verásReactDOM.render(<App />, document.getElementById('root')). Esa API está eliminada en React 19 y no funcionará. Usa siemprecreateRoot.
import './index.css';
Importar un CSS desde JavaScript resulta chocante la primera vez, pero es una funcionalidad de la herramienta de construcción, no de React: Vite ve el import, procesa la hoja de estilos y la inyecta en la página. Como no extraemos ningún valor del fichero, no hay llaves ni nombre de variable.
import App from './App.jsx';
Importación por defecto: por eso no lleva llaves. Se corresponde con el export default App; del final de App.jsx. Al ser por defecto, el nombre local es libre —podrías escribir import Raiz from './App.jsx'—, aunque por claridad se usa siempre el mismo.
La sentencia final. Léela de dentro hacia fuera:
document.getElementById('root')es JavaScript del DOM de toda la vida: obtiene eldivvacío del HTML.createRoot(...)convierte esediven una raíz gestionada por React y devuelve un objeto con un métodorender..render(...)recibe la descripción de la interfaz y la pinta dentro de la raíz.<App />es tu componente usado como si fuera una etiqueta. Fíjate en la barra final: los componentes sin contenido interno se autocierran, igual que<img />o<input />.
Es la única vez en toda la aplicación que llamarás a createRoot. A partir de aquí, todo lo demás es componentes dentro de componentes.
- Tu primer componente:
Bienvenida
BienvenidaCrea la carpeta donde vivirán los componentes de CicloUrbano y, dentro, el primero:
// src/componentes/Bienvenida.jsx
function Bienvenida() {
return (
<header>
<h1>CicloUrbano</h1>
<p>Alquila una bicicleta urbana en tu barrio, por horas y sin complicaciones.</p>
</header>
);
}
export default Bienvenida;Analicemos las cuatro partes:
function Bienvenida(): es una función de JavaScript normal y corriente. Sin parámetros, de momento.return (...): devuelve la descripción de un trozo de interfaz escrita en JSX. Los paréntesis trasreturnno son obligatorios cuando el JSX cabe en una línea, pero sí lo son en la práctica cuando ocupa varias: sin ellos, el punto y coma automático de JavaScript insertaría un;justo después dereturny la función devolveríaundefined.- Un único elemento raíz: todo el contenido está envuelto en
<header>. React necesita devolver una sola cosa; profundizarás en esta regla y en los fragmentos en la lección JSX. export default Bienvenida;: hace el componente importable desde otros ficheros.
Ahora úsalo en App.jsx:
// src/App.jsx
import Bienvenida from './componentes/Bienvenida.jsx';
function App() {
return (
<main>
<Bienvenida />
</main>
);
}
export default App;Guarda y mira el navegador: aparecen el título y el eslogan de CicloUrbano. Acabas de escribir y usar tu primer componente de React.
- Un componente es una función que devuelve JSX
Esta frase merece que la interiorices, porque es la definición completa:
Un componente de React es una función de JavaScript cuyo nombre empieza por mayúscula y que devuelve una descripción de interfaz (JSX).
No hay herencia, ni clases, ni registro en ningún sitio, ni configuración. Una función. Y como es una función, se usa como una etiqueta:
| Lo que escribes | Lo que hace React |
|---|---|
<Bienvenida /> |
Llama a la función Bienvenida() y coloca en ese punto lo que devuelve |
<Bienvenida></Bienvenida> |
Exactamente lo mismo; la forma autocerrada es la habitual cuando no hay contenido dentro |
Bienvenida() |
Llama a la función directamente. No lo hagas: React deja de tratarlo como un componente y pierde su identidad para el estado, DevTools y la reconciliación |
Puedes escribir el mismo componente con función flecha; ambas formas son equivalentes y verás las dos en proyectos reales:
// Declaración de función (la que usaremos en el curso)
function Bienvenida() {
return <h1>CicloUrbano</h1>;
}
// Función flecha asignada a una constante
const Bienvenida = () => {
return <h1>CicloUrbano</h1>;
};
// Función flecha con retorno implícito (sin llaves ni return)
const Bienvenida = () => <h1>CicloUrbano</h1>;En este curso usaremos la declaración de función porque su nombre aparece siempre de forma clara en los mensajes de error y en React DevTools, y porque no depende de la posición en el fichero.
Y como los componentes son funciones que devuelven descripciones de interfaz, se componen entre sí formando un árbol:
flowchart TD
R["Raíz de React (div#root)"] --> S[StrictMode]
S --> A[App]
A --> B[Bienvenida]
A --> T[TarjetaBicicleta]
- La convención de la mayúscula inicial
No es una preferencia de estilo: es una regla obligatoria. JSX decide qué hacer con una etiqueta mirando la primera letra de su nombre.
<header> // minúscula -> React entiende: etiqueta HTML estándar 'header'
<Bienvenida /> // mayúscula -> React entiende: mi componente llamado BienvenidaLa razón es que JSX se transforma en llamadas a una función, y en esa transformación la primera letra determina si el primer argumento es una cadena de texto o una referencia a tu función:
// Escribes esto:
<header />
<Bienvenida />
// Y se transforma, a grandes rasgos, en esto:
jsx('header', ...) // cadena: React crea un <header> del navegador
jsx(Bienvenida, ...) // referencia: React ejecuta tu funciónSi escribes tu componente en minúscula, React buscará una etiqueta HTML llamada bienvenida, no la encontrará como elemento conocido y el navegador la mostrará vacía. No verás un error rojo, solo una página incompleta, lo que convierte este fallo en uno de los más frustrantes para quien empieza.
| Nombre | ¿Válido? | Resultado |
|---|---|---|
Bienvenida |
Sí | Componente correcto |
TarjetaBicicleta |
Sí | Correcto; PascalCase para nombres compuestos |
bienvenida |
No | React busca una etiqueta HTML inexistente; no se pinta nada |
tarjeta_bicicleta |
No | Mismo problema, además de romper la convención de nombres |
Regla práctica: componentes en PascalCase, ficheros con el mismo nombre que el componente. Bienvenida vive en Bienvenida.jsx, TarjetaBicicleta en TarjetaBicicleta.jsx. Así encontrar el código de lo que ves en pantalla es inmediato.
- Segundo componente:
TarjetaBicicleta
TarjetaBicicletaVamos a crear la pieza más característica de CicloUrbano: la tarjeta que representa una bicicleta. En esta lección los datos van escritos a mano dentro del componente; hacerla flexible con datos que llegan de fuera es el objetivo de la lección Props.
// src/componentes/TarjetaBicicleta.jsx
function TarjetaBicicleta() {
return (
<article className="tarjeta-bicicleta">
<h3>Urbana Clásica</h3>
<p>Tipo: urbana</p>
<p>Estado: disponible</p>
<p>Estación: Plaza Mayor</p>
<p>
<strong>2,50 € / hora</strong>
</p>
</article>
);
}
export default TarjetaBicicleta;Dos detalles que quizá te hayan llamado la atención:
classNameen lugar declass.classes una palabra reservada de JavaScript, y JSX es JavaScript. Por eso React usaclassName. Es el error de novato más frecuente y lo veremos a fondo en la próxima lección.<article>y<h3>en lugar dedivpara todo. React no te libera de escribir HTML semántico: los componentes acaban produciendo etiquetas reales, y elegirlas bien beneficia a la accesibilidad y al SEO.
Los datos corresponden a la bicicleta bici-001 del dominio de CicloUrbano que fijamos en la lección 01-01.
Ahora úsalo, y de paso comprueba algo importante: el mismo componente se puede usar tantas veces como quieras.
// src/App.jsx
import Bienvenida from './componentes/Bienvenida.jsx';
import TarjetaBicicleta from './componentes/TarjetaBicicleta.jsx';
function App() {
return (
<main>
<Bienvenida />
<section>
<h2>Bicicletas destacadas</h2>
<TarjetaBicicleta />
<TarjetaBicicleta />
<TarjetaBicicleta />
</section>
</main>
);
}
export default App;En el navegador verás tres tarjetas idénticas. Que sean idénticas es precisamente la limitación que resolveremos con props: cada instancia recibirá su propia bicicleta y mostrará datos distintos. Pero el mecanismo de reutilización ya está a la vista, y es la esencia del modelo de componentes.
Añade unos estilos a src/index.css para que se vea presentable:
/* Añadir al final de src/index.css */
.tarjeta-bicicleta {
background: #ffffff;
border: 1px solid #d9e2ec;
border-radius: 8px;
padding: 1rem 1.25rem;
margin-bottom: 1rem;
max-width: 22rem;
}
.tarjeta-bicicleta h3 {
margin-bottom: 0.5rem;
color: #12805c;
}
.tarjeta-bicicleta p {
margin: 0.25rem 0;
font-size: 0.95rem;
}
React.StrictMode: qué es y por qué ves cosas dos veces
React.StrictMode: qué es y por qué ves cosas dos vecesVuelve a main.jsx y fíjate en que <App /> está envuelto en <StrictMode>:
StrictMode es un componente especial que no pinta absolutamente nada: no genera ninguna etiqueta en el DOM. Su único cometido es activar comprobaciones adicionales durante el desarrollo para detectar código problemático cuanto antes.
Lo que hace:
- Ejecuta tus componentes dos veces en cada render (solo en desarrollo). Sirve para descubrir efectos secundarios accidentales: si tu componente modifica una variable externa o hace algo más que calcular su interfaz, con dos ejecuciones el resultado será distinto y el fallo saldrá a la luz de inmediato en lugar de dentro de seis meses.
- Monta, desmonta y vuelve a montar cada componente al inicio, para verificar que la limpieza de efectos está bien escrita.
- Avisa de APIs obsoletas y de patrones desaconsejados.
De ahí la consecuencia que más desconcierta a quien empieza: si pones un console.log('renderizando') dentro de un componente, verás el mensaje dos veces en la consola. No es un fallo tuyo ni de React.
Compruébalo:
// src/componentes/Bienvenida.jsx
function Bienvenida() {
console.log('Se está ejecutando Bienvenida');
return (
<header>
<h1>CicloUrbano</h1>
<p>Alquila una bicicleta urbana en tu barrio, por horas y sin complicaciones.</p>
</header>
);
}
export default Bienvenida;La consola del navegador muestra el mensaje dos veces. Recuerda:
Con StrictMode (desarrollo) |
En producción | |
|---|---|---|
| Ejecuciones del componente | Dobles, a propósito | Una sola |
| Efectos al montar | Se ejecutan, limpian y repiten | Una sola vez |
| Impacto en el usuario final | Ninguno: solo afecta a npm run dev |
Ninguno |
No lo quites. La tentación de eliminar StrictMode para que la consola quede limpia es grande y es un error: estarías desactivando el detector de fallos precisamente donde sirve. La duplicación de efectos y su relación con useEffect se retoma con detalle en la lección Hook useEffect.
Borra ya el console.log antes de continuar.
- Ver el cambio en caliente
Con todo montado, aprovecha para experimentar y afianzar lo aprendido. Con npm run dev corriendo y el navegador al lado del editor:
- Cambia el eslogan de
Bienveniday guarda. El texto se actualiza al instante, sin recargar. - Cambia el modelo de
TarjetaBicicletaaEléctrica Proy el precio a4,00 € / hora. Las tres tarjetas cambian a la vez, porque las tres son la misma función devolviendo lo mismo. - Abre React DevTools, pestaña Components. Verás el árbol
App → Bienveniday tresTarjetaBicicleta. Observa queStrictModeaparece en el árbol de React pero no en la pestaña Elements del navegador: confirma que no genera HTML. - Comenta una de las tres
<TarjetaBicicleta />con{/* ... */}y comprueba que desaparece.
Ese bucle —editar, guardar, ver el resultado— es el ritmo de trabajo normal en React, y es la razón por la que el HMR de Vite importa tanto.
Errores Comunes y Consejos
- Olvidar el
export default. El import devuelveundefinedy React lanzaElement type is invalid: expected a string ... but got: undefined. Siempre que veas ese mensaje, revisa la pareja export/import del componente citado. - Confundir export por defecto y export con nombre.
export default Bienvenidase importa comoimport Bienvenida from ...;export function Bienvenidase importa comoimport { Bienvenida } from .... Mezclarlos daundefined. - Nombrar el componente en minúscula.
<bienvenida />no da error visible: simplemente no pinta nada. Si un componente «no aparece» y la consola está limpia, comprueba la mayúscula inicial antes que nada. - Poner el
returnen una línea y el JSX en la siguiente sin paréntesis. La inserción automática de punto y coma hace que la función devuelvaundefinedy React se queje de que nada se ha devuelto. Abre paréntesis en la misma línea delreturn. - Usar
ReactDOM.render. Está eliminado en React 19. Si un tutorial lo usa, está desactualizado; traduce acreateRoot(...).render(...). - Llamar al componente como función,
{Bienvenida()}. Funciona visualmente, pero React pierde la identidad del componente: no aparece en DevTools, no puede tener su propio estado ni participar bien en la reconciliación. Usa siempre<Bienvenida />. - Eliminar
StrictModeporque «la consola sale doble». Es el comportamiento esperado en desarrollo y desactivarlo esconde fallos reales. - Consejo: un componente por fichero, con el mismo nombre que el fichero, en
src/componentes/. Cuando CicloUrbano tenga treinta componentes lo agradecerás.
Ejercicios
Ejercicio 1
Crea un componente PieDePagina en src/componentes/PieDePagina.jsx que muestre, dentro de una etiqueta <footer>, el texto «CicloUrbano — Servicio de alquiler de bicicletas urbanas» y, en una segunda línea, «Estaciones: Plaza Mayor · Parque Norte · Estación Central». Úsalo en App.jsx debajo de las tarjetas.
Ejercicio 2
Este código no funciona. Localiza los tres errores y corrígelos explicando por qué falla cada uno.
// src/componentes/estacion.jsx
function estacion() {
return
<div class="estacion">
<h3>Plaza Mayor</h3>
<p>Barrio Centro · 20 plazas</p>
</div>;
}
export estacion;Ejercicio 3
Crea un componente TarjetaEstacion que muestre los datos de la estación est-02 del dominio de CicloUrbano (Parque Norte, barrio Norte, 15 plazas) con datos escritos a mano, y móntalo en App.jsx dentro de una <section> con el encabezado «Estaciones». Después responde: si quisieras mostrar las tres estaciones del dominio con este mismo componente, ¿qué limitación te encontrarías y en qué lección del curso se resuelve?
Soluciones
Solución 1.
// src/componentes/PieDePagina.jsx
function PieDePagina() {
return (
<footer>
<p>CicloUrbano — Servicio de alquiler de bicicletas urbanas</p>
<p>Estaciones: Plaza Mayor · Parque Norte · Estación Central</p>
</footer>
);
}
export default PieDePagina;// src/App.jsx
import Bienvenida from './componentes/Bienvenida.jsx';
import TarjetaBicicleta from './componentes/TarjetaBicicleta.jsx';
import PieDePagina from './componentes/PieDePagina.jsx';
function App() {
return (
<main>
<Bienvenida />
<section>
<h2>Bicicletas destacadas</h2>
<TarjetaBicicleta />
<TarjetaBicicleta />
<TarjetaBicicleta />
</section>
<PieDePagina />
</main>
);
}
export default App;Solución 2. Los tres errores:
- Nombre en minúscula.
function estacion()hace que<estacion />se interprete como una etiqueta HTML desconocida y no se pinte nada. Debe serTarjetaEstacion(PascalCase), y por coherencia el fichero debe llamarse igual. returnseguido de salto de línea sin paréntesis. JavaScript inserta un punto y coma automáticamente trasreturn, la función devuelveundefinedy React protesta. Hay que abrir el paréntesis en la misma línea delreturn.classen vez declassName.classes palabra reservada de JavaScript. En JSX se escribeclassName. (Yexport estacion;tampoco es sintaxis válida: faltadefault.)
// src/componentes/TarjetaEstacion.jsx
function TarjetaEstacion() {
return (
<div className="estacion">
<h3>Plaza Mayor</h3>
<p>Barrio Centro · 20 plazas</p>
</div>
);
}
export default TarjetaEstacion;Solución 3.
// src/componentes/TarjetaEstacion.jsx
function TarjetaEstacion() {
return (
<article className="tarjeta-estacion">
<h3>Parque Norte</h3>
<p>Barrio: Norte</p>
<p>Plazas: 15</p>
</article>
);
}
export default TarjetaEstacion;La limitación: los datos están escritos dentro del componente, así que las tres instancias mostrarían exactamente «Parque Norte, Norte, 15 plazas». Para que cada tarjeta muestre una estación distinta, el componente tiene que recibir los datos desde fuera. Ese mecanismo son las props, y se estudia en la lección Props: Pasando Datos a Componentes. Pintar una lista completa a partir de un array se verá en Listas y Claves.
Conclusión
Has pasado de ejecutar la plantilla de Vite a escribir tus propios componentes. Ahora sabes que index.html aporta un div#root vacío, que main.jsx lo convierte en raíz de React con createRoot(...).render(...) —nunca con el obsoleto ReactDOM.render—, y que un componente no es más que una función con nombre en mayúscula que devuelve JSX y se usa como una etiqueta. Has creado Bienvenida y TarjetaBicicleta, has comprobado que un mismo componente se reutiliza cuantas veces haga falta y entiendes por qué StrictMode ejecuta tu código dos veces en desarrollo.
Todo lo que has escrito dentro del return es JSX, y hasta ahora lo has usado por intuición: parece HTML y funciona casi como HTML. Casi. En la siguiente lección, JSX: Extensión de Sintaxis de JavaScript, verás en qué se transforma realmente, qué reglas lo separan del HTML y cómo insertar valores dinámicos con llaves para que tus tarjetas dejen de ser texto fijo.
Curso de React
Módulo 1: Introducción a React
- ¿Qué es React?
- Configuración del Entorno de Desarrollo
- Hola Mundo en React
- JSX: Extensión de Sintaxis de JavaScript
- Cómo Renderiza React: Virtual DOM y Reconciliación
Módulo 2: Componentes de React
- Entendiendo los Componentes
- Componentes Funcionales vs de Clase
- Props: Pasando Datos a Componentes
- State: Gestión del Estado del Componente
- Estilos en los Componentes: CSS, Módulos y Utilidades
Módulo 3: Trabajando con Eventos
- Manejo de Eventos en React
- Renderizado Condicional
- Listas y Claves
- Formularios y Componentes Controlados
- Validación de Formularios y Componentes No Controlados
- Accesibilidad en Componentes Interactivos
Módulo 4: Conceptos Avanzados de Componentes
- Elevando el Estado
- Composición vs Herencia
- Métodos del Ciclo de Vida de React
- Hooks: Introducción y Uso Básico
- Límites de Error: Capturar Fallos en la Interfaz
Módulo 5: Hooks de React
- Hook useState
- Hook useEffect
- Hook useRef y Acceso al DOM
- Hook useContext
- Hook useReducer
- Hooks Personalizados
Módulo 6: Enrutamiento en React
- Introducción a React Router
- Configuración de React Router
- Rutas Anidadas
- Navegación Programática
- Rutas Protegidas y Control de Acceso
Módulo 7: Gestión del Estado
- Introducción a la Gestión del Estado
- API de Contexto
- Redux: Introducción y Configuración
- Redux: Acciones y Reductores
- Redux: Conectando a React
- Estado del Servidor: Peticiones, Caché y Sincronización
Módulo 8: Optimización del Rendimiento
- Técnicas de Optimización del Rendimiento en React
- Memorización con React.memo
- Hooks useMemo y useCallback
- División de Código y Carga Perezosa
- Medir el Rendimiento con React DevTools Profiler
Módulo 9: Pruebas en React
- Introducción a las Pruebas
- Pruebas Unitarias con Jest
- Pruebas de Componentes con React Testing Library
- Pruebas de Código Asíncrono y Simulación de APIs
- Pruebas de Extremo a Extremo con Cypress
Módulo 10: Temas Avanzados
- Renderizado del Lado del Servidor (SSR) con Next.js
- Generación de Sitios Estáticos (SSG) con Next.js
- Suspense y React Server Components
- TypeScript con React
- React Native: Creación de Aplicaciones Móviles
