Importar y exportar componentes

La magia de los componentes reside en su reusabilidad: puedes crear componentes que se componen a su vez de otros componentes. Pero mientras anidas m√°s y m√°s componentes, a menudo tiene sentido comenzar a separarlos en diferentes archivos. Esto permite que tus archivos se mantengan f√°ciles de localizar y puedas reutilizar componentes en m√°s lugares.

Aprender√°s

  • Qu√© es un archivo de componente ra√≠z
  • C√≥mo importar y exportar un componente
  • Cu√°ndo usar imports y exports defaults o con nombre
  • C√≥mo importar o exportar m√ļltiples componentes de un archivo
  • C√≥mo separar componentes en m√ļltiples archivos

El archivo de componente raíz

En Tu primer componente, hiciste un componente Profile y un componente Gallery que lo renderiza:

function Profile() {
  return (
    <img
      src="https://i.imgur.com/MK3eW3As.jpg"
      alt="Katherine Johnson"
    />
  );
}

export default function Gallery() {
  return (
    <section>
      <h1>Amazing scientists</h1>
      <Profile />
      <Profile />
      <Profile />
    </section>
  );
}

Estos viven actualmente en este ejemplo en un archivo de componente raíz, llamado App.js. En Create React App, tu aplicación vive en src/App.js. No obstante, en dependencia de tu configuración, tu componente raíz podría estar en otro archivo. Si utilizas un framework con enrutamiento basado en archivos, como Next.js, tu componente raíz será diferente para cada página.

Exportar e importar un componente

¬ŅY si quisieras cambiar la pantalla de inicio en el futuro y poner all√≠ una lista de libros cient√≠ficos? ¬ŅO ubicar todos los perfiles en otro lugar? Tiene sentido mover Gallery y Profile fuera del componente ra√≠z. Esto los har√≠a m√°s modulares y reutilizables en otros archivos. Puedes mover un componente en tres pasos:

  1. Crea un nuevo archivo JS para poner los componentes dentro.
  2. Exporta tu componente de función desde ese archivo (ya sea usando exports por defecto o con nombre).
  3. Impórtalo en el archivo en el que usarás el componente (usando la técnica correspondiente de importar exports por defecto o con nombre).

Aquí tanto Profile y Gallery se han movido fuera de App.js en un nuevo archivo llamado Gallery.js. Ahora puedes cambiar App.js para importar Gallery desde Gallery.js:

import Gallery from './Gallery.js';

export default function App() {
  return (
    <Gallery />
  );
}

Nota cómo este ejemplo está ahora descompuesto en dos archivos:

  1. Gallery.js:
    • Define el componente Profile que se usa solo dentro del mismo archivo y no se exporta.
    • Define el componente Gallery como un export por defecto.
  2. App.js:
    • Importa Gallery como un import por defecto desde Gallery.js.
    • Exporta el componente ra√≠z App como un export por defecto.

Nota

Puede que te encuentres archivos que omiten la extensión de archivo .js de esta forma:

import Gallery from './Gallery';

Tanto './Gallery.js' como './Gallery' funcionarán con React, aunque la primera forma es más cercana a cómo lo hacen los módulos nativos de ES.

Deep Dive

Exports por defecto vs. con nombre

Hay dos formas fundamentales de exportar valores con JavaScript: exports por defecto y exports con nombre. Hasta ahora nuestros ejemplos solo han usado exports por defecto. Pero puedes usar uno o ambos en el mismo archivo. Un archivo no puede tener m√°s de un export por defecto, pero puede tener tantos exports con nombre como desees.

Exports por defecto y con nombre

Cómo exportas tu componente dicta la forma en que debes importarlo. ¡Tendrás un error si intentas importar un export por defecto de la misma forma que lo harías con un export con nombre! Este cuadro te puede ayudar a recordarlo:

SintaxisSentencia exportSentencia import
Por defectoexport default function Button() {}import Button from './button.js';
Con nombreexport function Button() {}import { Button } from './button.js';

Cuando escribes un import por defecto puedes poner cualquier nombre después de import. Por ejemplo, podrías escribir en su lugar import Banana from './button.js' y aun así te daría el mismo export por defecto. En cambio, con los imports con nombre, tiene que haber una correspondencia con los nombres en ambos lados. ¡Por eso se llaman exports con nombre!

Las personas a menudo utilizan exports por defecto si el archivo solo exporta un componente, y usan exports con nombre si exporta varios componentes y valores. Independientemente del estilo de codificación que prefieras, siempre proporciona nombres con sentido a las funciones de tus componentes y a los archivos que las contienen. Componentes sin nombre como export default () => {} no se recomiendan, porque hacen que la depuración sea más difícil.

Exportar e importar m√ļltiples componentes del mismo archivo

¬ŅY si quisieras mostrar solo un Profile en lugar de toda la galer√≠a? Puedes exportar el componente Profile tambi√©n. Pero Gallery.js ya tiene un export por defecto, y no puedes tener dos exports por defecto. Podr√≠as crear un nuevo archivo con un export por defecto, o podr√≠as a√Īadir un export con nombre para Profile. ¬°Un archivo solo puede contener un export por defecto, pero puede tener m√ļltiples exports con nombre!

Para reducir la potencial confusión entre exports por defecto y con nombre, algunos equipos escogen utilizar solo un estilo (por defecto o con nombre), o evitan mezclarlos en un mismo archivo. Es una cuestión de preferencias. ¡Haz lo que funcione mejor para ti!

Primero, exporta Profile desde Gallery.js usando un export con nombre (sin la palabra clave default):

export function Profile() {
// ...
}

Luego, importa Profile desde Gallery.js hacia App.js usando un export con nombre (con llaves):

import { Profile } from './Gallery.js';

Por √ļltimo, renderiza <Profile /> en el componente App:

export default function App() {
return <Profile />;
}

Ahora Gallery.js contiene dos exports: un export por defecto Gallery, y un export con nombre Profile. App.js importa ambos. Intenta editar <Profile /> cambi√°ndolo a <Gallery /> y viceversa en este ejemplo:

import Gallery from './Gallery.js';
import { Profile } from './Gallery.js';

export default function App() {
  return (
    <Profile />
  );
}

Ahora est√°s usando a una mezcla de exports por defecto y con nombre:

  • Gallery.js:
    • Exporta el componente Profile como un export con nombre llamado Profile.
    • Exporta el componente Gallery como un export por defecto.
  • App.js:
    • Importa Profile como un import con nombre llamado Profile desde Gallery.js.
    • Importa Gallery como un import por defecto desde Gallery.js.
    • Exporta el componente ra√≠z App como un export por defecto.

Recapitulación

En esta p√°gina aprendiste:

  • Qu√© es un archivo de componente ra√≠z
  • Como importar y exportar un componente
  • Cu√°ndo y c√≥mo usar imports y exports por defecto y con nombre
  • C√≥mo exportar m√ļltiples componentes desde el mismo archivo

Desafío 1 de 1:
Separa los componentes a√ļn m√°s

Actualmente, Gallery.js exporta tanto Profile como Gallery, lo cual es un poco confuso.

Mueve el componente Profile a su propio Profile.js, y luego cambia el componente App para que renderice tanto <Profile /> como <Gallery /> uno detr√°s del otro.

Puedes usar o bien un export por defecto o bien un export con nombre para Profile, ¬°pero aseg√ļrate de usar la sintaxis de import correspondiente tanto en App.js como en Gallery.js! Te puedes apoyar en la tabla de la secci√≥n de profundizaci√≥n de arriba:

SintaxisSentencia exportSentencia import
Por defectoexport default function Button() {}import Button from './button.js';
Con nombreexport function Button() {}import { Button } from './button.js';
// Move me to Profile.js!
export function Profile() {
  return (
    <img
      src="https://i.imgur.com/QIrZWGIs.jpg"
      alt="Alan L. Hart"
    />
  );
}

export default function Gallery() {
  return (
    <section>
      <h1>Amazing scientists</h1>
      <Profile />
      <Profile />
      <Profile />
    </section>
  );
}

Después de tenerlo funcionando con un tipo de export, hazlo funcionar con el otro tipo.