Опис інтерфейсу

React - це JavaScript бібліотека для рендерингу інтерфейсів користувача (UI). UI будується з невеликих блоків, таких як кнопки, текст та зображення. React дозволяє об'єднувати їх у багаторазові, вкладені компоненти. Від веб-сайтів до телефонних застосунків, все на екрані можна розбити на компоненти. У цьому розділі ви навчитеся створювати, налаштовувати та умовно відображати React-компоненти.

Ваш перший компонент

React-застосунки збираються з ізольованих частин інтерфейсу користувача, які називаються компонентами. React-компонент - це JavaScript-функція, яку ви можете посипати розміткою. Компоненти можуть бути як маленькими, як кнопка, так і великими, як ціла сторінка. Ось компонент Gallery, який рендерить три компоненти Profile:

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; }

Прочитайте Ваш перший компонент, щоб дізнатися, як оголошувати та використовувати React-компоненти.

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

В одному файлі можна оголосити багато компонентів, але у великих файлах може бути важко орієнтуватися. Щоб вирішити цю проблему, ви можете експортувати компонент у його власний файл, а потім імпортувати цей компонент з іншого файлу:

import Gallery from './Gallery.js';

export default function App() {
  return (
    <Gallery />
  );
}
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; }

Прочитайте Імпорт та експорт компонентів, щоб дізнатися, як розділити компоненти на власні файли.

Запис розмітки за допомогою JSX

Кожен React-компонент - це JavaScript-функція, яка може містити деяку розмітку, яку React відображає в браузері. Для представлення цієї розмітки React-компоненти використовують синтаксичне розширення JSX. JSX дуже схожий на HTML, але він трохи суворіший і може відображати динамічну інформацію.

Якщо вставити існуючу HTML-розмітку в React-компонент, це не завжди буде працювати:

export default function TodoList() {
  return (
    // This doesn't quite work!
    <h1>Hedy Lamarr's Todos</h1>
    <img
      src="https://i.imgur.com/yXOvdOSs.jpg"
      alt="Hedy Lamarr"
      class="photo"
    >
    <ul>
      <li>Invent new traffic lights
      <li>Rehearse a movie scene
      <li>Improve spectrum technology
    </ul>
  );
}
img { height: 90px; }

Якщо у вас вже є подібний HTML, ви можете виправити його за допомогою конвертера:

export default function TodoList() {
  return (
    <>
      <h1>Hedy Lamarr's Todos</h1>
      <img
        src="https://i.imgur.com/yXOvdOSs.jpg"
        alt="Hedy Lamarr"
        className="photo"
      />
      <ul>
        <li>Invent new traffic lights</li>
        <li>Rehearse a movie scene</li>
        <li>Improve spectrum technology</li>
      </ul>
    </>
  );
}
img { height: 90px; }

Прочитайте Запис розмітки за допомогою JSX, щоб дізнатися, як писати правильний JSX.

JavaScript у JSX з фігурними дужками

JSX дозволяє писати HTML-подібну розмітку всередині JavaScript-файлу, зберігаючи логіку рендерингу та вміст в одному місці. Іноді вам може знадобитися додати трохи JavaScript-логіки або послатися на динамічну властивість всередині цієї розмітки. У цій ситуації ви можете використовувати фігурні дужки у вашому JSX, щоб відкрити вікно для JavaScript:

const person = {
  name: 'Gregorio Y. Zara',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

export default function TodoList() {
  return (
    <div style={person.theme}>
      <h1>{person.name}'s Todos</h1>
      <img
        className="avatar"
        src="https://i.imgur.com/7vQD0fPs.jpg"
        alt="Gregorio Y. Zara"
      />
      <ul>
        <li>Improve the videophone</li>
        <li>Prepare aeronautics lectures</li>
        <li>Work on the alcohol-fuelled engine</li>
      </ul>
    </div>
  );
}
body { padding: 0; margin: 0 }
body > div > div { padding: 20px; }
.avatar { border-radius: 50%; height: 90px; }

Прочитайте JavaScript у JSX з фігурними дужками, щоб дізнатися, як отримати доступ до даних JavaScript з JSX.

Передача пропсів до компонента

Компоненти React використовують пропси для спілкування один з одним. Кожен батьківський компонент може передавати певну інформацію своїм дочірнім компонентам, надаючи їм пропси. Пропси можуть нагадувати вам атрибути HTML, але ви можете передавати через них будь-які значення JavaScript, включаючи об'єкти, масиви, функції і навіть JSX!

import { getImageUrl } from './utils.js'

export default function Profile() {
  return (
    <Card>
      <Avatar
        size={100}
        person={{
          name: 'Katsuko Saruhashi',
          imageId: 'YfeOqp2'
        }}
      />
    </Card>
  );
}

function Avatar({ person, size }) {
  return (
    <img
      className="avatar"
      src={getImageUrl(person)}
      alt={person.name}
      width={size}
      height={size}
    />
  );
}

function Card({ children }) {
  return (
    <div className="card">
      {children}
    </div>
  );
}
export function getImageUrl(person, size = 's') {
  return (
    'https://i.imgur.com/' +
    person.imageId +
    size +
    '.jpg'
  );
}
.card {
  width: fit-content;
  margin: 5px;
  padding: 5px;
  font-size: 20px;
  text-align: center;
  border: 1px solid #aaa;
  border-radius: 20px;
  background: #fff;
}
.avatar {
  margin: 20px;
  border-radius: 50%;
}

Прочитайте Передача пропсів компоненту, щоб дізнатися, як передавати та читати пропси.

Умовний рендеринг

Вашим компонентам часто буде потрібно відображати різні речі залежно від різних умов. У React ви можете умовно рендерити JSX, використовуючи синтаксис JavaScript, наприклад, оператори if, && та ? :.

У цьому прикладі оператор JavaScript && використовується для умовного відображення позначки:

function Item({ name, isPacked }) {
  return (
    <li className="item">
      {name} {isPacked && '✔'}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item
          isPacked={true}
          name="Space suit"
        />
        <Item
          isPacked={true}
          name="Helmet with a golden leaf"
        />
        <Item
          isPacked={false}
          name="Photo of Tam"
        />
      </ul>
    </section>
  );
}

Прочитайте Умовне відображення, щоб дізнатися про різні способи умовного відображення вмісту.

Списки рендерингу

Вам часто буде потрібно відображати декілька схожих компонентів з набору даних. Ви можете використовувати filter() та map() JavaScript у React для фільтрації та перетворення масиву даних на масив компонентів.

Для кожного елемента масиву потрібно вказати ключ. Зазвичай, ви хочете використовувати ідентифікатор з бази даних як ключ. Ключі дозволяють React відстежувати місце кожного елемента у списку, навіть якщо список змінюється.

import { people } from './data.js';
import { getImageUrl } from './utils.js';

export default function List() {
  const listItems = people.map(person =>
    <li key={person.id}>
      <img
        src={getImageUrl(person)}
        alt={person.name}
      />
      <p>
        <b>{person.name}:</b>
        {' ' + person.profession + ' '}
        known for {person.accomplishment}
      </p>
    </li>
  );
  return (
    <article>
      <h1>Scientists</h1>
      <ul>{listItems}</ul>
    </article>
  );
}
export const people = [{
  id: 0,
  name: 'Creola Katherine Johnson',
  profession: 'mathematician',
  accomplishment: 'spaceflight calculations',
  imageId: 'MK3eW3A'
}, {
  id: 1,
  name: 'Mario José Molina-Pasquel Henríquez',
  profession: 'chemist',
  accomplishment: 'discovery of Arctic ozone hole',
  imageId: 'mynHUSa'
}, {
  id: 2,
  name: 'Mohammad Abdus Salam',
  profession: 'physicist',
  accomplishment: 'electromagnetism theory',
  imageId: 'bE7W1ji'
}, {
  id: 3,
  name: 'Percy Lavon Julian',
  profession: 'chemist',
  accomplishment: 'pioneering cortisone drugs, steroids and birth control pills',
  imageId: 'IOjWm71'
}, {
  id: 4,
  name: 'Subrahmanyan Chandrasekhar',
  profession: 'astrophysicist',
  accomplishment: 'white dwarf star mass calculations',
  imageId: 'lrWQx8l'
}];
export function getImageUrl(person) {
  return (
    'https://i.imgur.com/' +
    person.imageId +
    's.jpg'
  );
}
ul { list-style-type: none; padding: 0px 10px; }
li {
  margin-bottom: 10px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
}
img { width: 100px; height: 100px; border-radius: 50%; }
h1 { font-size: 22px; }
h2 { font-size: 20px; }

Прочитайте Рендеринг списків, щоб дізнатися, як рендерити список компонентів та як вибрати ключ.

Збереження чистоти компонентів

Деякі функції JavaScript є чистими.Чиста функція:

  • Займається своїми справами. Не змінює жодних об'єктів чи змінних, які існували до його виклику.
  • Ті самі входи, той самий вихід. При однакових входах чиста функція завжди повинна повертати однаковий результат.

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

let guest = 0;

function Cup() {
  // Bad: changing a preexisting variable!
  guest = guest + 1;
  return <h2>Tea cup for guest #{guest}</h2>;
}

export default function TeaSet() {
  return (
    <>
      <Cup />
      <Cup />
      <Cup />
    </>
  );
}

Цей компонент можна зробити чистим, передавши проп замість того, щоб змінювати вже існуючу змінну:

function Cup({ guest }) {
  return <h2>Tea cup for guest #{guest}</h2>;
}

export default function TeaSet() {
  return (
    <>
      <Cup guest={1} />
      <Cup guest={2} />
      <Cup guest={3} />
    </>
  );
}

Прочитайте Збереження чистоти компонентів, щоб дізнатися, як писати компоненти як чисті, передбачувані функції.

Ваш інтерфейс як дерево

React використовує дерева для моделювання зв'язків між компонентами та модулями.

Дерево рендерингу React - це представлення батьківських та дочірніх відносин між компонентами

A tree graph with five nodes, with each node representing a component. The root node is located at the top the tree graph and is labelled 'Root Component'. It has two arrows extending down to two nodes labelled 'Component A' and 'Component C'. Each of the arrows is labelled with 'renders'. 'Component A' has a single 'renders' arrow to a node labelled 'Component B'. 'Component C' has a single 'renders' arrow to a node labelled 'Component D'.

Приклад дерева рендерингу React.

Компоненти біля вершини дерева, біля кореневого компонента, вважаються компонентами верхнього рівня. Компоненти, які не мають дочірніх компонентів, є листовими компонентами. Така категоризація компонентів є корисною для розуміння потоку даних та продуктивності рендерингу.

Моделювання взаємозв'язку між модулями JavaScript - ще один корисний спосіб зрозуміти ваш застосунок. Ми називаємо його деревом залежностей модулів.

A tree graph with five nodes. Each node represents a JavaScript module. The top-most node is labelled 'RootModule.js'. It has three arrows extending to the nodes: 'ModuleA.js', 'ModuleB.js', and 'ModuleC.js'. Each arrow is labelled as 'imports'. 'ModuleC.js' node has a single 'imports' arrow that points to a node labelled 'ModuleD.js'.

Приклад дерева залежностей модуля.

Дерево залежностей часто використовується інструментами збірки для об'єднання всього відповідного JavaScript коду для завантаження та рендерингу клієнтом. Великий розмір пакету погіршує користувацький досвід React-застосунків. Розуміння дерева залежностей модуля допомагає налагодити такі проблеми.

Прочитайте Ваш інтерфейс як дерево, щоб дізнатися, як створювати дерева візуалізації та про залежності модулів для React-застосунку і як вони є корисними ментальними моделями для покращення користувацького досвіду та продуктивності.

Що далі?

Перейдіть до розділу Ваш перший компонент, щоб почати читати цей розділ сторінка за сторінкою!

Або, якщо ви вже знайомі з цими темами, чому б не прочитати про Додавання інтерактивності?