Списки и ключи в React

ReactBeginner
Практиковаться сейчас

Введение

В React вам часто потребуется отображать несколько похожих компонентов из коллекции данных. Вы можете использовать методы массивов JavaScript, такие как map(), для манипулирования массивом данных и преобразования его в массив JSX-элементов.

"Key" (ключ) — это специальный строковый атрибут, который необходимо включать при создании списков элементов. Ключи помогают React определять, какие элементы изменились, были добавлены или удалены. Это позволяет React эффективно обновлять пользовательский интерфейс.

В этой лабораторной работе вы научитесь брать массив данных, преобразовывать его в список компонентов и рендерить, а также поймете критическую роль свойства key.

Создайте массив элементов в компоненте

На этом шаге вы начнете с определения данных, которые хотите отобразить в виде списка. В большинстве приложений эти данные поступали бы из API или базы данных, но для этой лабораторной работы мы определим простой массив непосредственно внутри нашего компонента.

Сначала убедитесь, что вы находитесь в правильном каталоге. Ваше React-приложение my-app было создано в каталоге /home/labex/project.

Используя файловый менеджер в левой части WebIDE, откройте файл my-app/src/App.jsx.

Внутри функции компонента App, перед оператором return, определите константу с именем products, которая будет массивом строк.

function App() {
  const products = ["Laptop", "Mouse", "Keyboard", "Monitor"];

  return (
    <>
      <h1>My Product List</h1>
    </>
  );
}

export default App;

На данный момент массив определен, но еще не отрендерен. Следующий шаг покажет вам, как отобразить эти данные.

Преобразуйте массив в JSX-элементы с помощью метода map

На этом шаге вы будете использовать метод map() JavaScript для преобразования вашего массива products в список JSX-элементов. Метод map() создает новый массив, вызывая функцию для каждого элемента исходного массива.

Мы преобразуем каждую строку продукта в элемент <li> (элемент списка).

Измените файл src/App.jsx. Внутри оператора return вставьте логику сопоставления (mapping) в фигурные скобки {}.

function App() {
  const products = ["Laptop", "Mouse", "Keyboard", "Monitor"];

  const listItems = products.map((product) => <li>{product}</li>);

  return (
    <>
      <h1>My Product List</h1>
      {listItems}
    </>
  );
}

export default App;

Теперь давайте установим зависимости проекта и запустим сервер разработки, чтобы увидеть результат.

Откройте новый терминал в WebIDE. Сначала перейдите в каталог вашего проекта:

cd my-app

Затем установите зависимости:

npm install

Наконец, запустите сервер разработки. Флаги --host и --port необходимы для того, чтобы приложение было доступно в среде LabEx.

npm run dev -- --host 0.0.0.0 --port 8080

После запуска сервера переключитесь на вкладку Web 8080 в вашем интерфейсе LabEx. Вы должны увидеть список ваших продуктов. Однако, если вы откроете консоль разработчика браузера (щелкните правой кнопкой мыши -> Inspect -> Console), вы увидите предупреждение: Warning: Each child in a list should have a unique "key" prop. Мы исправим это на следующем шаге.

Предупреждение консоли разработчика об отсутствующем свойстве key

Назначьте уникальный prop 'key' каждому элементу списка

На этом шаге вы исправите предупреждение в консоли, предоставив уникальный key каждому элементу списка. Ключи имеют решающее значение для React, чтобы отслеживать идентификатор каждого элемента, что помогает эффективно перерисовывать список при изменении данных.

Лучший способ выбрать ключ — использовать строку, которая однозначно идентифицирует элемент списка среди его соседей. Чаще всего вы будете использовать идентификаторы из ваших данных.

Давайте изменим наши данные, чтобы они представляли собой массив объектов, где каждый объект имеет уникальный id. Обновите src/App.jsx следующим образом. Мы будем использовать id каждого продукта в качестве его ключа.

function App() {
  const products = [
    { id: "p1", name: "Laptop" },
    { id: "p2", name: "Mouse" },
    { id: "p3", name: "Keyboard" },
    { id: "p4", name: "Monitor" }
  ];

  const listItems = products.map((product) => (
    <li key={product.id}>{product.name}</li>
  ));

  return (
    <>
      <h1>My Product List</h1>
      {listItems}
    </>
  );
}

export default App;

Обратите внимание на свойство key={product.id}, добавленное к элементу <li>. Ключ — это специальное свойство, которое используется React внутренне и не передается вашему компоненту.

После сохранения файла снова проверьте вкладку Web 8080 и консоль разработчика. Список должен отобразиться как и раньше, но предупреждение об отсутствующих ключах исчезнет.

Используйте индекс в качестве ключа, если нет уникального идентификатора

На этом шаге вы узнаете, как обрабатывать ситуации, когда ваши данные не имеют стабильных, уникальных идентификаторов. В таких случаях в качестве крайней меры можно использовать индекс элемента в массиве.

Функция map() предоставляет индекс текущего элемента в качестве необязательного второго аргумента. Вы можете использовать этот индекс для ключа.

Давайте вернем наш массив products к простому массиву строк и используем индекс в качестве ключа. Измените src/App.jsx:

function App() {
  const products = ["Laptop", "Mouse", "Keyboard", "Monitor"];

  const listItems = products.map((product, index) => (
    <li key={index}>{product}</li>
  ));

  return (
    <>
      <h1>My Product List</h1>
      {listItems}
    </>
  );
}

export default App;

Важное примечание: Использование индекса в качестве ключа не рекомендуется, если порядок элементов может измениться. Это может негативно сказаться на производительности и вызвать проблемы с состоянием компонентов. Если вы сортируете, добавляете или удаляете элементы из списка, индексы изменятся, что может сбить с толку алгоритм рендеринга React. Используйте его только в том случае, если список статичен и никогда не будет переупорядочен.

Отобразите сопоставленный список внутри тега ul или ol

На этом шаге вы обернете элементы вашего списка в тег <ul> (неупорядоченный список) или <ol> (упорядоченный список). Это важно для создания семантически корректного HTML, что хорошо для доступности (accessibility) и SEO.

В настоящее время мы отображаем серию элементов <li> непосредственно внутри фрагмента (<>...</>). Давайте обернем нашу переменную listItems в тег <ul>, чтобы создать правильный неупорядоченный список.

Обновите ваш src/App.jsx с финальным кодом:

function App() {
  const products = ["Laptop", "Mouse", "Keyboard", "Monitor"];

  const listItems = products.map((product, index) => (
    <li key={index}>{product}</li>
  ));

  return (
    <>
      <h1>My Product List</h1>
      <ul>{listItems}</ul>
    </>
  );
}

export default App;

Теперь вернитесь на вкладку Web 8080. Вы увидите, что ваш список теперь правильно отформатирован с помощью маркеров, как и ожидается от стандартного HTML-элемента <ul>. Вы успешно отобразили динамический список в React с правильными ключами и семантическим HTML.

React list rendered as unordered HTML list

Резюме

Поздравляем с завершением лабораторной работы!

В этой лабораторной работе вы изучили основные концепции рендеринга списков в React. Вы практиковались в следующем:

  • Определение массива данных внутри компонента.
  • Использование метода map() для преобразования массива данных в массив JSX-элементов.
  • Критическая важность свойства key для элементов списка, чтобы помочь React с эффективным рендерингом.
  • Как использовать стабильные, уникальные идентификаторы из ваших данных в качестве ключей.
  • Как использовать индекс массива в качестве ключа в крайнем случае и связанные с этим потенциальные недостатки.
  • Оборачивание элементов списка в <ul> или <ol> для семантического HTML.

Эти навыки необходимы для создания динамических и управляемых данными приложений с помощью React.