JS: React
Теория: Children
UI-элементы имеют иерархическую структуру. Например, компонент card в Bootstrap:
Блок карточки может содержать внутри себя картинку и тело. Тело, в свою очередь, может состоять из заголовка и текста, а текст может быть чем угодно. То же самое применимо как к самым простым элементам самого HTML, например, тегу <div>, так и к остальным компонентам Bootstrap, таким как модальные окна и навигация.
HTML соответствует природе UI и естественным образом позволяет создавать композиции элементов за счёт вкладывания тегов друг в друга. Точно так же работает и JSX. Пока эта возможность использовалась в курсе только для встроенных компонентов. Теперь пора научиться повторять подобное поведение в самописных компонентах. В качестве примера взят компонент <Alert /> из Bootstrap.
https://codepen.io/hexlet/pen/YxgWVm
В примере выше обязательной частью является только основной div. Содержимое зависит от конкретной ситуации. Подставляется оно с помощью свойства children.
https://codepen.io/hexlet/pen/GveqMp
Обратите внимание на то, что компонент стал использоваться как парный тег в JSX:
Все, что находится между открывающим и закрывающим тегом, попадает внутрь пропса children.
Но будьте бдительны: тип данных свойства children зависит от содержимого. В простейшем случае, когда тег используется как одиночный <div />, это свойство будет равно undefined:
Если этим содержимым является строка, то именно она окажется внутри children. Правда, после некоторой обработки. JSX удаляет пробельные символы с начала и конца строки, включая пустые строки. Следующие примеры будут отображены одинаково:
Любой одиночный дочерний компонент также будет представлен сам собой в children:
Во всех остальных случаях children будет содержать массив:
Если внимательно посмотреть на документацию React, то можно увидеть следующее определение children: "children are an opaque data structure" (свойство children — непрозрачная структура данных). Другими словами, нельзя однозначно полагаться на тип этого пропса, так как снаружи можно передать всё что угодно.
Подобное поведение может приводить к трудно находимым ошибкам. Например, проверка this.props.children.length — это не всегда количество детей. Если children это одиночный элемент, например строка, то свойство length вернет длину этой строки.
Именно поэтому React предоставляет набор функций, предназначенных для манипулирования пропсом children. Все они доступны в React.Children. Эти функции знают про особенности работы children, сами проверяют тип и делают нужные проверки в зависимости от типа данных.
React.Children.map()
https://codepen.io/hexlet/pen/ayMZrr
Из урока про обработку коллекций вы можете вспомнить, что при работе со списком каждому элементу нужно установить проп key. Если этого не сделать в случае с React.Children.map, React не выбросит предупреждение. Так сделано намеренно, поскольку у потомков обычно нет уникальных идентификаторов.
React.Children.count()
Чтобы получить количество детей, нужно использовать метод React.Children.count(). В него передается children. Узлы, которые не являются DOM-элементами, будут проигнорированы:
Кроме перечисленного выше, бывает необходимо обработать дочерние элементы перед выводом, изменив часть в пропсе. Конечно же, напрямую этого сделать нельзя, ведь пропсы неизменяемы. Такого поведения можно добиться, клонируя элементы функцией React.cloneElement().
Композиция компонентов
Иерархия компонентов во многом закладывает структуру приложения. То, как вы распределите приложение на компоненты, определит кодовую базу вашего проекта.
Есть несколько советов как разбивать приложение на компоненты:
- выделите части интерфейса в приложении, которые имеют осмысленный функционал. Например: навигационная панель, боковое меню, окно чата и т.д. Каждую такую часть приложения можно выделить в отдельный компонент. Такое разбиение интерфейса на составляющие части заложит основу компонентной базы
- если какие-то элементы повторяются, то их тоже лучше выделить в отдельный компонент для переиспользования. Например, это могут быть Button и InputField
- рассматривайте компоненты как чистые функции. Пропсы, как и параметры в чистых функциях, не изменяются в компонентах, в React это важное правило




