Рендеринг списков
Часто требуется отображать несколько похожих компонентов из коллекции данных. Для работы с массивом данных можно использоватьметоды массивов JavaScript. На этой странице вы будете использоватьfilter() и map()в React для фильтрации и преобразования вашего массива данных в массив компонентов.
Вы изучите
- Как рендерить компоненты из массива с помощью JavaScript-метода
map() - Как рендерить только определённые компоненты с помощью JavaScript-метода
filter() - Когда и зачем использовать ключи React
Рендеринг данных из массивов
Допустим, у вас есть список контента.
Единственное различие между этими элементами списка — их содержимое, их данные. При создании интерфейсов часто требуется показывать несколько экземпляров одного и того же компонента с разными данными: от списков комментариев до галерей изображений профилей. В таких ситуациях можно хранить эти данные в объектах и массивах JavaScript и использовать методы вродеmap() и filter()для рендеринга списков компонентов из них.
Вот краткий пример того, как сгенерировать список элементов из массива:
- Переместитеданные в массив:
- Преобразуйтеэлементы
peopleв новый массив JSX-узлов,listItems:
- Верните
listItemsиз вашего компонента, обёрнутые в<ul>:
Вот результат:
Обратите внимание, что в песочнице выше отображается ошибка консоли:
Консоль
Предупреждение: Каждый дочерний элемент в списке должен иметь уникальный проп «key».
Вы узнаете, как исправить эту ошибку, далее на этой странице. Прежде чем мы перейдём к этому, давайте добавим некоторую структуру вашим данным.
Фильтрация массивов элементов
Эти данные можно структурировать ещё лучше.
Допустим, вам нужен способ показывать только людей, чья профессия —'chemist'. Можно использовать метод JavaScriptfilter(), чтобы вернуть только этих людей. Этот метод принимает массив элементов, пропускает их через «тест» (функцию, возвращающуюtrueилиfalse) и возвращает новый массив только тех элементов, которые прошли тест (вернулиtrue).
Вам нужны только элементы, гдеprofessionравен'chemist'. Функция «теста» для этого выглядит так:(person) => person.profession === 'chemist'. Вот как это объединить:
- Создайтеновый массив только из людей с профессией «химик»,
chemists, вызвавfilter()для массиваpeopleс условиемperson.profession === 'chemist':
- Теперьпреобразуйтемассив
chemistsс помощьюmap():
- Наконец,верните
listItemsиз вашего компонента:
Подводный камень
Стрелочные функции неявно возвращают выражение, стоящее сразу после=>, поэтому вам не нужен операторreturn:
Однаковы должны явно написатьreturn, если после=>следует{(фигурная скобка)!
Стрелочные функции, содержащие=> {, называются функциями с«блочным телом».Они позволяют писать более одной строки кода, но выобязанысами написать операторreturn. Если вы забудете его, ничего не будет возвращено!
Поддержание порядка элементов списка с помощьюkey
Обратите внимание, что все песочницы выше показывают ошибку в консоли:
Консоль
Предупреждение: Каждый дочерний элемент в списке должен иметь уникальный проп «key».
Вам нужно присвоить каждому элементу массиваkey— строку или число, которое уникально идентифицирует его среди других элементов этого массива:
Примечание
Элементам JSX, находящимся непосредственно внутри вызоваmap(), всегда нужны ключи!
Ключи сообщают React, какому элементу массива соответствует каждый компонент, чтобы он мог сопоставить их позже. Это становится важным, если элементы вашего массива могут перемещаться (например, из-за сортировки), вставляться или удаляться. Правильно выбранныйkeyпомогает React понять, что именно произошло, и внести правильные обновления в дерево DOM.
Вместо того чтобы генерировать ключи на лету, вы должны включать их в свои данные:
Откуда братьkey
Разные источники данных предоставляют разные источники ключей:
- Данные из базы данных:Если ваши данные поступают из базы данных, вы можете использовать ключи/ID базы данных, которые по своей природе уникальны.
- Локально сгенерированные данные:Если ваши данные генерируются и сохраняются локально (например, заметки в приложении для заметок), используйте инкрементный счётчик,crypto.randomUUID()или пакет вродеuuidпри создании элементов.
Правила ключей
- Ключи должны быть уникальными среди соседних элементов.Однако можно использовать одинаковые ключи для JSX-узлов вразныхмассивах.
- Ключи не должны меняться, иначе это лишает их смысла! Не генерируйте их во время рендеринга.
Зачем React нужны ключи?
Представьте, что файлы на вашем рабочем столе не имеют имён. Вместо этого вы бы ссылались на них по порядку — первый файл, второй файл и так далее. Вы могли бы привыкнуть к этому, но после удаления файла это стало бы запутанным. Второй файл стал бы первым, третий файл — вторым и так далее.
Имена файлов в папке и ключи JSX в массиве служат схожей цели. Они позволяют нам однозначно идентифицировать элемент среди его соседей. Правильно выбранный ключ предоставляет больше информации, чем позиция в массиве. Даже еслипозицияизменится из-за переупорядочивания,keyпозволяет React идентифицировать элемент на протяжении всего его жизненного цикла.
Подводный камень
У вас может возникнуть соблазн использовать индекс элемента в массиве в качестве его ключа. Фактически, React будет использовать именно это, если вы не укажетеkey. Но порядок, в котором вы отображаете элементы, будет меняться со временем, если элемент будет вставлен, удалён или массив будет переупорядочен. Использование индекса в качестве ключа часто приводит к тонким и запутанным ошибкам.
Аналогично, не генерируйте ключи на лету, например, с помощьюkey={Math.random()}. Это приведёт к тому, что ключи никогда не будут совпадать между рендерами, что заставит все ваши компоненты и DOM пересоздаваться каждый раз. Это не только медленно, но и приведёт к потере любых пользовательских данных внутри элементов списка. Вместо этого используйте стабильный ID, основанный на данных.
Обратите внимание, что ваши компоненты не получаютkeyв качестве пропса. Он используется только как подсказка самим React. Если вашему компоненту нужен ID, вы должны передать его как отдельный пропс:<Profile key={id} userId={id} />.
Итоги
На этой странице вы узнали:
- Как выносить данные из компонентов в структуры данных, такие как массивы и объекты.
- Как генерировать наборы похожих компонентов с помощью JavaScript-метода
map(). - Как создавать массивы отфильтрованных элементов с помощью JavaScript-метода
filter(). - Зачем и как задавать
keyдля каждого компонента в коллекции, чтобы React мог отслеживать их, даже если их положение или данные изменятся.
Try out some challenges
Challenge 1 of 4:Splitting a list in two #
This example shows a list of all people.
Change it to show two separate lists one after another: Chemists and Everyone Else. Like previously, you can determine whether a person is a chemist by checking if person.profession === 'chemist'.
