Saltar al contenido principal
Logo de JSCamp

Módulos JavaScript - Import y Export

Aprende a organizar tu código en módulos, exportar e importar componentes, y las mejores prácticas para estructurar aplicaciones React

midudev

Más clases y directos en YouTube

Suscribirse

Módulos JavaScript - Import y Export

Hasta ahora hemos tenido todo nuestro código en un solo archivo App.jsx. En aplicaciones reales, separamos el código en múltiples archivos usando el sistema de módulos de JavaScript. En esta clase aprenderemos a exportar e importar componentes.

El problema: Todo en un archivo

Imagina que tienes toda tu aplicación en App.jsx:

// App.jsx - 500 líneas de código 😱function Header() {  return <header>...</header>}function Footer() {  return <footer>...</footer>}function JobCard({ job }) {  return <article>...</article>}function JobList({ jobs }) {  return <div>...</div>}function SearchForm() {  return <form>...</form>}function App() {  return (    <div>      <Header />      <SearchForm />      <JobList />      <Footer />    </div>  )}export default App

Problemas:

  • 📜 Difícil de leer - 500+ líneas en un archivo
  • 🔍 Difícil de encontrar - ¿Dónde está el componente que necesito?
  • 🐛 Difícil de depurar - Todo mezclado
  • 👥 Difícil de colaborar - Conflictos en Git
  • ♻️ No reutilizable - No puedes usar estos componentes en otros archivos

La solución: Módulos

Separamos cada componente en su propio archivo y usamos import / export:

src/├── components/│   ├── Header.jsx│   ├── Footer.jsx│   ├── JobCard.jsx│   ├── JobList.jsx│   └── SearchForm.jsx└── App.jsx

Separando un componente a otro archivo

Vamos a separar el componente Header paso a paso.

Paso 1: Crear el archivo

Crea src/components/Header.jsx:

// src/components/Header.jsxfunction Header() {  return (    <header className="header">      <div className="container">        <h1>DevJobs</h1>        <nav>          <a href="#jobs">Trabajos</a>          <a href="#about">Acerca</a>          <a href="#contact">Contacto</a>        </nav>      </div>    </header>  )}export default Header

¿Qué hace export default?

  • Marca el componente para que pueda ser importado desde otros archivos
  • default significa que es la exportación principal del archivo
  • Solo puede haber un export default por archivo

Paso 2: Importar en App.jsx

Ahora en App.jsx importamos el componente:

// src/App.jsximport Header from './components/Header'function App() {  return (    <div className="app">      <Header />      {/* Resto de la aplicación */}    </div>  )}export default App

¿Qué hace import?

  • import Header - El nombre que usarás en este archivo
  • from './components/Header' - La ruta al archivo (sin extensión .jsx)
  • ./ significa “carpeta actual”

¡Listo! El componente está separado y funcionando.

Export Default vs Export Named

Hay dos formas de exportar en JavaScript:

1. Export Default (por defecto)

Un solo export principal por archivo:

// Header.jsxfunction Header() {  return <header>...</header>}export default Header

Importar:

// Puedes usar CUALQUIER nombre al importarimport Header from './components/Header'import MyHeader from './components/Header' // ✅ También funcionaimport Cabecera from './components/Header' // ✅ También funciona

Ventajas:

  • ✅ Simple para componentes principales
  • ✅ Puedes renombrar al importar
  • ✅ Menos código

Desventajas:

  • ⚠️ No sabes el nombre original del componente
  • ⚠️ Diferentes nombres en diferentes archivos (confuso)
  • ⚠️ No hay autocomplete del nombre

2. Export Named (nombrado)

Múltiples exports por archivo:

// Header.jsxexport function Header() {  return <header>...</header>}export function HeaderLogo() {  return <img src="logo.png" alt="Logo" />}export function HeaderNav() {  return <nav>...</nav>}

Importar:

// Debes usar el NOMBRE EXACTO con llaves {}import { Header, HeaderLogo, HeaderNav } from './components/Header'

Ventajas:

  • ✅ Nombres consistentes en toda la aplicación
  • ✅ Autocomplete funciona mejor
  • ✅ Puedes exportar múltiples cosas
  • ✅ Más explícito y claro
  • ✅ Mejor para tree-shaking (optimización)

Desventajas:

  • ⚠️ Más verboso (necesitas las llaves {})
  • ⚠️ Debes recordar el nombre exacto

Por qué preferimos Named Exports

En React moderno, preferimos named exports por varias razones:

1. Consistencia

// ❌ Con default export (cada archivo puede usar diferente nombre)// App.jsximport Header from './components/Header'// OtherPage.jsximport MyHeader from './components/Header'// AnotherPage.jsximport TopBar from './components/Header'// 😱 Tres nombres diferentes para el mismo componente!
// ✅ Con named export (siempre el mismo nombre)// App.jsximport { Header } from './components/Header'// OtherPage.jsximport { Header } from './components/Header'// AnotherPage.jsximport { Header } from './components/Header'// 🎉 Mismo nombre en todos lados!

2. Refactoring seguro

Con named exports, si renombras el componente, tu IDE puede actualizar todas las referencias automáticamente.

3. Autocomplete

// Con named export, tu IDE sugiere:import { Header } from './components/Header'//       ^ Autocomplete del nombre exacto// Con default export:import Header from './components/Header'//     ^ Tienes que recordar/adivinar el nombre

4. Múltiples exports

// utils.js - Puedes exportar varias funcionesexport function formatDate(date) {  // ...}export function formatCurrency(amount) {  // ...}export function formatPhone(phone) {  // ...}// Importar solo lo que necesitasimport { formatDate, formatCurrency } from './utils'

Sintaxis de Named Export

Hay dos formas de escribir named exports:

Forma 1: Export inline (recomendada)

// Header.jsxexport function Header() {  return <header>...</header>}export function HeaderLogo() {  return <img src="logo.png" />}

Forma 2: Export al final

// Header.jsxfunction Header() {  return <header>...</header>}function HeaderLogo() {  return <img src="logo.png" />}// Al final del archivoexport { Header, HeaderLogo }

Ambas son equivalentes. La primera es más común en React.

Renombrando imports

A veces necesitas renombrar un import para evitar colisiones de nombres:

Problema: Colisión de nombres

// ❌ Error: Ambos se llaman "Button"import { Button } from './components/Button'import { Button } from './ui/Button'

Solución 1: Renombrar con as

// ✅ Renombrar uno de ellosimport { Button } from './components/Button'import { Button as UIButton } from './ui/Button'function App() {  return (    <div>      <Button>Componente Button</Button>      <UIButton>UI Button</UIButton>    </div>  )}

Solución 2: Renombrar ambos

// ✅ Nombres más descriptivosimport { Button as PrimaryButton } from './components/Button'import { Button as SecondaryButton } from './ui/Button'function App() {  return (    <div>      <PrimaryButton>Principal</PrimaryButton>      <SecondaryButton>Secundario</SecondaryButton>    </div>  )}

Ejemplo real: Colisión con nombres comunes

// Dos componentes diferentes llamados "Card"import { Card as JobCard } from './components/JobCard'import { Card as UserCard } from './components/UserCard'function Dashboard() {  return (    <div>      <JobCard job={job} />      <UserCard user={user} />    </div>  )}

Rutas de importación

Rutas relativas

// Mismo directorioimport { Header } from './Header'// Subdirectorioimport { Header } from './components/Header'// Directorio padreimport { Header } from '../Header'// Dos niveles arribaimport { Header } from '../../Header'

Import de múltiples elementos

Puedes importar varios elementos a la vez:

// Importar múltiples named exportsimport { Header, Footer, Nav } from './components'// Importar default + namedimport App, { config, API_URL } from './App'// Importar todo como namespaceimport * as Utils from './utils'Utils.formatDate()Utils.formatCurrency()

Errores comunes

1. Olvidar el export

// ❌ Error: No exportadofunction Header() {  return <header>...</header>}// ✅ Correctoexport function Header() {  return <header>...</header>}

2. Mezclar default y named imports

// Header.jsxexport function Header() {  return <header>...</header>}// ❌ Error: Header no es default exportimport Header from './components/Header'// ✅ Correcto: Usar llaves para namedimport { Header } from './components/Header'

3. Ruta incorrecta

// ❌ Error: Falta el ./import { Header } from 'components/Header'// ✅ Correcto: Rutas relativas empiezan con ./import { Header } from './components/Header'

4. Olvidar la extensión en algunos bundlers

// Vite: No necesitas extensiónimport { Header } from './components/Header' // ✅// Algunos bundlers antiguos:import { Header } from './components/Header.jsx' // Puede ser necesario

¡Resumiendo que es gerundio!

En esta clase has aprendido:

  • 📦 Módulos - Separar código en múltiples archivos
  • 📤 Export default - Una exportación principal por archivo
  • 📤 Export named - Múltiples exportaciones con nombres específicos
  • 📥 Import - Traer código de otros archivos
  • 🔄 Renombrar imports - Usar as para evitar colisiones
  • 🎯 Named exports preferidos - Más consistentes y mantenibles
  • 🗂️ Estructura - Organizar componentes en carpetas

En la próxima clase aprenderemos sobre CSS Modules, una forma de escribir CSS con scope local para evitar conflictos de estilos entre componentes.

💡 Recuerda: Usa named exports (export function ComponentName) en lugar de default exports para mantener consistencia y aprovechar mejor el autocomplete. Organiza tu código en archivos pequeños y enfocados en una sola responsabilidad.