Імпорт та експорт компонентів

Магія компонентів полягає у їх повторному використанні: ви можете створювати компоненти, які складаються з інших компонентів. Але коли ви вкладаєте все більше і більше компонентів, часто має сенс почати розбивати їх на окремі файли. Це дозволить вам легко зберігати файли для сканування і повторно використовувати компоненти у більшій кількості місць.

  • Що таке файл кореневого компонента
  • Як імпортувати та експортувати компонент
  • Коли використовувати стандартний та іменований імпорт та експорт
  • Як імпортувати та експортувати декілька компонентів з одного файлу
  • Як розділити компоненти на декілька файлів

Кореневий файл компонента

У вашому першому компоненті ви створили компонент Profile та компонент Gallery, який його рендерить:

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>
  );
}
img { margin: 0 10px 10px 0; height: 90px; }

Наразі вони знаходяться у кореневому файлі компонентів , з назвою App.js у цьому прикладі. Однак, залежно від ваших налаштувань, кореневий компонент може знаходитися у іншому файлі. Якщо ви використовуєте фреймворк з файловою маршрутизацією, наприклад Next.js, ваш кореневий компонент буде різним для кожної сторінки.

Експорт та імпорт компонента

А якщо ви захочете в майбутньому змінити лендінговий екран і розмістити там список наукових книг? Або розмістити всі профілі в іншому місці? Має сенс перемістити Gallery і Profile з кореневого файлу компонентів. Це зробить їх більш модульними і придатними для повторного використання в інших файлах. Ви можете перемістити компонент у три кроки:

  1. Створіть новий JS-файл для розміщення компонентів.
  2. Експортуйте ваш функціональний компонент з цього файлу (за допомогою стандартного або названого експорту).
  3. Імпортуйте його у файл, де ви будете використовувати компонент (використовуючи відповідну техніку для імпорту за замовчуванням або іменованого експорту).

Тут обидва Profile і Gallery було переміщено з App.js у новий файл з назвою Gallery.js. Тепер ви можете змінити App.js на імпорт Gallery з Gallery.js:

import Gallery from './Gallery.js';

export default function App() {
  return (
    <Gallery />
  );
}
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>
  );
}
img { margin: 0 10px 10px 0; height: 90px; }

Зверніть увагу, як цей приклад тепер розбито на два файли компонентів:

  1. Gallery.js:
    • Визначає компонент Profile, який використовується лише у межах одного файла і не експортується.
    • Експорт компонента Gallery як експорт за замовчуванням.
  2. App.js:
    • Імпортує Gallery як імпорт за замовчуванням з Gallery.js.
    • Експортує кореневий App компонент як експорт за замовчуванням.

Ви можете зустріти файли, у яких не вказано розширення файлу .js, наприклад:

import Gallery from './Gallery';

З React працюватимуть або './Gallery.js', або './Gallery', хоча перший варіант ближчий до того, як працюють нативні модулі ES.

Експорт за замовчуванням проти іменованого експорту

Існує два основних способи експорту значень за допомогою JavaScript: експорт за замовчуванням та іменований експорт. Досі в наших прикладах використовувався лише експорт за замовчуванням. Але ви можете використовувати один або обидва способи в одному файлі. Файл може мати не більше одного експорту за замовчуванням, але він може мати стільки іменованих експортів, скільки ви хочете.

Default and named exports

Спосіб експорту вашого компонента визначає спосіб його імпорту. Ви отримаєте помилку, якщо спробуєте імпортувати експорт за замовчуванням так само, як і іменований експорт! Ця таблиця може допомогти вам відстежувати:

Синтаксис Оператор експорту Оператор імпорту
За замовчуванням export default function Button() {} import Button from './Button.js';
Іменований export function Button() {} import { Button } from './Button.js';

Коли ви пишете імпорт за замовчуванням, ви можете поставити будь-яку назву після імпорту. Наприклад, ви можете написати import Banana from './Button.js', і ви отримаєте той самий експорт за замовчуванням. На відміну від цього, при іменованому імпорті ім'я має збігатися з обох сторін. Ось чому вони називаються іменованими імпортами!

Часто використовують експорт за замовчуванням, якщо файл експортує лише один компонент, та іменований експорт, якщо він експортує декілька компонентів і значень. Незалежно від того, якому стилю кодування ви надаєте перевагу, завжди давайте осмислені назви функціям компонентів і файлам, які їх містять. Не рекомендується використовувати компоненти без назв, наприклад export default () => {}, оскільки вони ускладнюють налагодження.

Експорт та імпорт декількох компонентів з одного файлу

Що, якщо ви хочете показати лише один Profile замість галереї? Ви також можете експортувати компонент Profile. Але Gallery.js вже має експорт за замовчуванням, а ви не можете мати два експорти за замовчуванням. Ви можете створити новий файл з експортом за замовчуванням або додати експорт з назвою для Profile. Файл може мати лише один експорт за замовчуванням, але він може мати багато іменованих експортів!

Щоб зменшити потенційну плутанину між типовим та іменованим експортом, деякі команди вирішують дотримуватися лише одного стилю (типового або іменованого) або уникати їх змішування в одному файлі. Робіть так, як вам зручніше!

По-перше, експортуйте Profile з Gallery.js за допомогою іменованого експорту (без ключового слова за замовчуванням):

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

Потім, імпортуйте Profile з Gallery.js до App.js за допомогою іменованого імпорту (з фігурними дужками):

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

Нарешті, відрендеримо <Profile /> з компонента App:

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

Тепер Gallery.js містить два експорти: експорт за замовчуванням Gallery та іменований Profile. App.js імпортує обидва. Спробуйте змінити <Profile /> на <Gallery /> і назад у цьому прикладі:

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

export default function App() {
  return (
    <Profile />
  );
}
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>
  );
}
img { margin: 0 10px 10px 0; height: 90px; }

Тепер ви використовуєте суміш типового та іменованого експорту:

  • Gallery.js:
    • Експортує компонент Profile як іменований експорт з назвою Profile.
    • Експорт компонента Gallery як експорт за замовчуванням.
  • App.js:
    • Імпортує Profile як іменований імпорт з назвою Profile з Gallery.js.
    • Імпортує Gallery як імпорт за замовчуванням з Gallery.js.
    • Експортує кореневий App компонент як експорт за замовчуванням.

На цій сторінці ви дізналися:

  • Що таке кореневий файл компонента
  • Як імпортувати та експортувати компонент
  • Коли і як використовувати стандартний та іменований імпорт та експорт
  • Як експортувати декілька компонентів з одного файлу

Розділіть компоненти далі

Наразі Gallery.js експортує як Profile, так і Gallery, що трохи заплутує.

Перемістіть компонент Profile до його власного Profile.js, а потім змініть компонент App так, щоб він відображав <Profile /> та <Gallery /> один за одним.

Ви можете використовувати стандартний або іменований експорт для Profile, але переконайтеся, що ви використовуєте відповідний синтаксис імпорту в App.js і Gallery.js! Ви можете звернутися до таблиці з глибокого занурення вище:

Синтаксис Оператор експорту Оператор імпорту
За замовчуванням export default function Button() {} import Button from './Button.js';
Іменований export function Button() {} import { Button } from './Button.js';

Не забудьте імпортувати компоненти туди, де вони викликаються. Хіба Gallery не використовує Profile також?

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

export default function App() {
  return (
    <div>
      <Profile />
    </div>
  );
}
// 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>
  );
}
</pre>
<pre><code class="language-css">img { margin: 0 10px 10px 0; height: 90px; }

Після того, як ви налагодите роботу з одним типом експорту, зробіть так, щоб він працював з іншим типом.

Це рішення з іменованим експортом:

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

export default function App() {
  return (
    <div>
      <Profile />
      <Gallery />
    </div>
  );
}
import { Profile } from './Profile.js';

export default function Gallery() {
  return (
    <section>
      <h1>Amazing scientists</h1>
      <Profile />
      <Profile />
      <Profile />
    </section>
  );
}
export function Profile() {
  return (
    <img
      src="https://i.imgur.com/QIrZWGIs.jpg"
      alt="Alan L. Hart"
    />
  );
}
img { margin: 0 10px 10px 0; height: 90px; }

Це рішення з експортом за замовчуванням:

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

export default function App() {
  return (
    <div>
      <Profile />
      <Gallery />
    </div>
  );
}
import Profile from './Profile.js';

export default function Gallery() {
  return (
    <section>
      <h1>Amazing scientists</h1>
      <Profile />
      <Profile />
      <Profile />
    </section>
  );
}
export default function Profile() {
  return (
    <img
      src="https://i.imgur.com/QIrZWGIs.jpg"
      alt="Alan L. Hart"
    />
  );
}
img { margin: 0 10px 10px 0; height: 90px; }