Migrando el Proyecto DevJobs a React
Ya tenemos nuestro proyecto React con Vite configurado. Ahora vamos a migrar nuestro proyecto DevJobs que teníamos en HTML puro a React.
La estrategia que vamos a seguir es simple:
- Empezar con todo el HTML en un solo componente
- Identificar problemas (como los comentarios HTML)
- Separar en componentes progresivamente
Creando el componente inicial con todo el HTML
Lo primero que haremos es crear un componente que contenga todo el HTML de nuestro proyecto DevJobs.
No te preocupes si al principio parece un componente gigante con mucho código. Este es el primer paso natural al migrar de HTML a React.
Copiando el HTML
Abre tu App.jsx y vamos a poner todo el HTML de DevJobs dentro del return:
function App() {
return (
<div>
<!-- Aquí iría todo tu HTML de DevJobs -->
<header>
<nav>...</nav>
</header>
<main>
<section>...</section>
</main>
<footer>
<p>...</p>
</footer>
</div>
)
}
export default App
Este es un buen primer paso. Tener todo en un componente nos permite:
- ✅ Verificar que el HTML funciona en React
- ✅ Identificar problemas de sintaxis
- ✅ Ver la aplicación funcionando antes de refactorizar
Problema con los comentarios HTML
Cuando copies tu HTML a JSX, te encontrarás con un error importante: los comentarios HTML no funcionan en JSX.
Comentarios en HTML vs JSX
En HTML normal escribíamos:
<!-- Este es un comentario en HTML -->
<div>Contenido</div>
Pero en JSX, esto da error:
// ❌ ESTO NO FUNCIONA
function App() {
return (
<div>
<!-- Este comentario rompe JSX -->
<h1>Hola</h1>
</div>
)
}
¿Por qué fallan los comentarios HTML?
Recuerda que JSX no es HTML, es JavaScript que se transforma a llamadas de React:
// Esto:
<div><!-- comentario --><h1>Hola</h1></div>
// Se intenta transformar a:
React.createElement('div', null, '<!-- comentario -->', React.createElement('h1', null, 'Hola'))
// ❌ Pero '<!-- comentario -->' no es válido en JavaScript
La solución: Comentarios en JSX
En JSX, los comentarios se escriben como expresiones de JavaScript:
// ✅ Así se comentan cosas en JSX
function App() {
return (
<div>
{/* Este es un comentario en JSX */}
<h1>Hola</h1>
{/*
Los comentarios pueden
ocupar múltiples líneas
*/}
<p>Contenido</p>
</div>
)
}
Sintaxis:
{
/* Tu comentario aquí */
}
- Empieza con
{/* - Termina con
*/} - Es una expresión de JavaScript dentro de llaves
Reemplazando comentarios
Cuando migres tu HTML, busca todos los comentarios y reemplázalos:
// ❌ Antes (HTML)
<!-- Header principal -->
<header>
<!-- Navegación -->
<nav>...</nav>
</header>
// ✅ Después (JSX)
{/* Header principal */}
<header>
{/* Navegación */}
<nav>...</nav>
</header>
💡 Tip: Puedes buscar en tu editor
<!--para encontrar todos los comentarios HTML y reemplazarlos por comentarios JSX.
Separando en componentes: Header y Footer
Ahora que tenemos todo funcionando en un solo componente, es hora de empezar a separar en componentes más pequeños.
Comenzaremos con los más fáciles: el Header y el Footer.
¿Por qué Header y Footer primero?
- 🎯 Son independientes del resto de la aplicación
- 📦 Tienen una responsabilidad clara
- 🔄 No cambian frecuentemente
- ✅ Son fáciles de identificar y extraer
Creando el componente Header
Crea un nuevo archivo src/components/Header.jsx:
function Header() {
return (
<header>
<nav>
<div className="logo">
<h1>DevJobs</h1>
</div>
<ul>
<li>
<a href="#jobs">Trabajos</a>
</li>
<li>
<a href="#about">Acerca</a>
</li>
<li>
<a href="#contact">Contacto</a>
</li>
</ul>
</nav>
</header>
)
}
export default Header
Pasos que seguimos:
- Crear archivo nuevo -
Header.jsxen carpetacomponents/ - Definir función -
function Header() { ... } - Copiar el HTML - Del
<header>completo - Exportar -
export default Header
Creando el componente Footer
Crea otro archivo src/components/Footer.jsx:
function Footer() {
return (
<footer>
<div className="footer-content">
<p>© 2024 DevJobs. Todos los derechos reservados.</p>
<div className="social-links">
<a href="#twitter">Twitter</a>
<a href="#linkedin">LinkedIn</a>
<a href="#github">GitHub</a>
</div>
</div>
</footer>
)
}
export default Footer
Usando los componentes en App
Ahora, en App.jsx, importa y usa estos componentes:
import Header from './components/Header'
import Footer from './components/Footer'
function App() {
return (
<div className="app">
<Header />
<main>
{/* Aquí seguirá el resto del contenido por ahora */}
<section>
<h2>Trabajos Disponibles</h2>
{/* ... */}
</section>
</main>
<Footer />
</div>
)
}
export default App
¿Qué ganamos?
- ✅ App.jsx más limpio - Menos líneas de código
- ✅ Componentes reutilizables - Puedes usar Header en otras páginas
- ✅ Más fácil de mantener - Cambios al header en un solo lugar
- ✅ Mejor organización - Cada cosa en su archivo
Estructura de carpetas
Tu proyecto ahora debería verse así:
src/
├── components/
│ ├── Header.jsx # ← Nuevo
│ └── Footer.jsx # ← Nuevo
├── App.jsx # ← Modificado (usa Header y Footer)
└── main.jsx
Ventajas de separar en componentes
1. Código más organizado
// ❌ Todo en un archivo - Difícil de leer
function App() {
return <div>{/* 500 líneas de HTML aquí... */}</div>
}
// ✅ Separado en componentes - Fácil de entender
function App() {
return (
<div>
<Header />
<JobList />
<Footer />
</div>
)
}
2. Más fácil de mantener
Si necesitas cambiar el footer, solo editas Footer.jsx:
// Antes: buscar el footer entre 500 líneas
// Ahora: abrir Footer.jsx directamente
3. Reutilizable
Puedes usar el mismo Header en múltiples páginas:
// pages/Home.jsx
<Header />
// pages/Jobs.jsx
<Header />
// pages/About.jsx
<Header />
4. Testeable
Puedes probar cada componente individualmente:
// tests/Header.test.jsx
test('Header muestra el logo correctamente', () => {
render(<Header />)
// ...
})
Próximos pasos
Ahora que tenemos Header y Footer separados, en las siguientes clases vamos a:
- Separar la lista de trabajos en un componente
JobList - Crear componente para cada trabajo individual:
JobCard - Manejar el estado de los trabajos (favoritos, filtros, etc.)
- Agregar interactividad con eventos y estado
Patrón de migración
Este patrón que hemos seguido es muy común al migrar proyectos:
1. Todo en un componente
└── Verificar que funciona
2. Identificar piezas independientes
└── Header, Footer, etc.
3. Extraer a componentes
└── Crear archivos separados
4. Importar y usar
└── Componer en App.jsx
5. Repetir con piezas más complejas
└── JobList, JobCard, etc.
Este enfoque progresivo es mejor que intentar separar todo de una vez.
Errores comunes al migrar
1. Olvidar cambiar class por className
// ❌ HTML
<div class="header">
// ✅ JSX
<div className="header">
2. No cerrar etiquetas self-closing
// ❌ HTML (funciona)
<img src="logo.png">
<input type="text">
// ✅ JSX (obligatorio cerrar)
<img src="logo.png" />
<input type="text" />
3. Olvidar el export
// ❌ Sin export - no se puede importar
function Header() {
return <header>...</header>
}
// ✅ Con export
export function Header() {
return <header>...</header>
}
4. No importar el componente
// ❌ Sin import - error
function App() {
return <Header /> // ← "Header is not defined"
}
// ✅ Con import
import Header from './components/Header'
function App() {
return <Header />
}
¡Resumiendo que es gerundio!
- 📋 Migración progresiva - Empezar con todo en un componente
- 💬 Comentarios en JSX - Usar
{/* */}en lugar de<!-- --> - 🧩 Separar componentes - Header y Footer como primeros pasos
- 📁 Organizar archivos - Carpeta
components/para componentes - ♻️ Reutilización - Componentes que puedes usar múltiples veces
- 🎯 Patrón de migración - Del HTML monolítico a componentes pequeños
En la próxima clase continuaremos separando más componentes y aprenderemos a pasar datos entre componentes usando props.
💡 Recuerda: No intentes separar todo en componentes desde el principio. Empieza con todo funcionando en un solo componente y ve separando progresivamente. Es más fácil y menos propenso a errores.