Подробное руководство по итерации, контексту и дочерним элементам в React

Подробное руководство по итерации, контексту и дочерним элементам в React

От автора: самые сложные этапы освоения React включают итерацию по наборам информации, передачу данных по всему приложению и работу с props.children. В этой статье мы подробно рассмотрим эти три концепции, охватив их внутреннюю работу с несколькими соответствующими примерами.

Чтобы следовать этому руководству, вы можете создать ветку в репозитории CodeSandBox. Вы также можете посмотреть здесь: GitHub Gist. Давайте начнем!

Итерация наследуемых элементов React

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

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

В нашем стартовом коде вы заметите, что у нас есть данные об исходных 150 покемонах в файле /src/data/data.js в качестве примера. Создайте новый файл с именем src/components/Pokemon.js со следующим шаблоном:

Теперь давайте импортируем компонент в наше приложение:

Давайте посмотрим, как мы можем перебрать наш Pokemon, используя традиционный цикл for:

Создать пустой массив

Для каждого элемента в массиве мы будем добавлять выражение JSX в массив.

Мы будем отображать массив в возвращенном JSX компоненте.

Добавьте приведенный ниже код в Pokemon.js:

Обратите внимание на key prop в теге section. Всякий раз, когда мы создаем массив JSX, элемент верхнего уровня всегда должен иметь key prop с уникальным значением, помогая React повторно отображать эти массивы более эффективно.

Хотя этот код работает, он слишком большой. Мы потенциально могли бы очистить код с помощью цикла for of, например:

Мы по-прежнему получаем желаемый результат, однако логика пользовательского интерфейса немного «рассеивается», а не остается в возвращаемом значении компонента. Мы можем использовать метод массива, map, как более плавный подход к циклу по массиву:

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

В нашем примере описанный выше процесс будет выглядеть следующим образом:

Теперь вся логика представления наших компонентов находится в одном месте. Хотя иногда бывает сложно уложиться в map. Во фреймворке SolidJS, который также использует JSX, есть компонент built для зацикливания данных. Я создал аналогичный компонент в своей библиотеке React merced-react-hooks, который загружается в стартовый код.

Используя компонент loop, мы можем абстрагировать map следующим образом:

Теперь мы видим огромную разницу в нашем коде, но дополнительная семантика может упростить его понимание.

Использование компонентов в итерации

Мы можем сделать наш код еще чище, создав компонент, отвечающий за отрисовку одного покемона. Создайте новый файл с именем src/components/OnePokemon.js со следующим кодом:

Теперь мы можем очистить компонент Pokemon и сделать его еще более понятным. Добавьте приведенный ниже код в Pokemon.js:

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

Props.children

Children — это prop, который не требует явного объявления в следующем стиле:

Вместо этого prop Children состоит из всего, что находится между открывающим и закрывающим тегами компонента. Создайте новый файл src/components/Children.js. Добавьте следующий шаблон в Children.js:

Давайте используем наш компонент children.js в App.js:

Код между открытым и закрывающим тегами передается как children prop и поэтому регистрируется. Это можно использовать достаточно гибко. Попробуйте следующий код, а затем просмотрите результаты console.log:

Теперь children должен содержать массив:

И children теперь должен содержать функцию:

Children теперь должен быть массивом с текстом в качестве первого элемента и функцией в качестве второго. По сути, вы можете передавать любой тип данных в качестве children prop, и вы даже можете передавать несколько значений в качестве children prop.

Мы можем использовать это в своих интересах. Обновите код еще раз следующим образом:

Обратите внимание, что функция выглядит как компонент, функция, которая получает props и возвращает JSX. Давайте рефакторим Children.js, чтобы воспользоваться этим:

Мы смогли использовать children prop в качестве компонента, потому что это была функция, отвечающая правилам компонента.

Сhildren позволяет нам создавать довольно уникальные служебные компоненты. Я создал функцию createTransform, чтобы упростить процесс внутри библиотеки merced-react-hooks. createTransform создает компоненты, которые выполняют преобразование своих дочерних элементов, например настраивают формат даты или капитализацию.

Давайте используем createTransform, чтобы сделать имя каждого покемона полностью заглавным и розовым:

Передача данных в ваше приложение

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

У нас может быть несколько контекстов для доставки разных типов данных. Давайте создадим контекст для доставки данных. По сути, мы будем следовать схеме ниже:

Создадим новый объект контекста

Создадим переменную или состояние, если данные могут измениться

Создадим пользовательский компонент, чтобы обернуть провайдера. Провайдер — это компонент, отвечающий за доступность контекста.

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

Создайте src/context/Theme.js:

Теперь мы можем импортировать компонент-оболочку в Index.js:

Мы можем легко извлекать эти данные из любого места, где они нам нужны, с помощью пользовательского хука. Вернемся к OnePokemon.js:

Использование React Context для передачи состояния

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

Создадим новый контекст

Создадим новый компонент-оболочку, который объявляет состояние и определяет функцию для изменения этого состояния желаемым образом.

Provider получает объект с состоянием и вспомогательной функцией

Пользовательский хук доставляет данные туда, где это необходимо

Добавьте приведенный ниже код в Counter.js:

index.js:

Теперь создайте src/components/Counter.js и используйте CounterContext следующим образом:

Давайте используем этот новый компонент в App.js:

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

Заключение

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

Автор: Alex Merced

Источник: blog.logrocket.com

Редакция: Команда webformyself.

Читайте нас в Telegram, VK, Яндекс.Дзен

Метки:

Похожие статьи:

Комментарии Вконтакте:

Комментарии запрещены.