Компоненты и пропсы¶
Компоненты позволяют разбить интерфейс на независимые части, про которые легко думать в отдельности. Их можно складывать вместе и использовать несколько раз. На этой странице мы ознакомимся с самой идеей компонентов.
Во многом компоненты ведут себя как обычные функции JavaScript. Они принимают произвольные входные данные (так называемые «пропсы») и возвращают React-элементы, описывающие, что мы хотим увидеть на экране.
Функциональные и классовые компоненты¶
Проще всего объявить React-компонент как функцию:
1 2 3 |
|
Эта функция — компонент, потому что она получает данные в одном объекте («пропсы») в качестве параметра и возвращает React-элемент. Мы будем называть такие компоненты «функциональными», так как они буквально являются функциями.
Ещё компоненты можно определять как классы ES6:
1 2 3 4 5 |
|
С точки зрения React, эти два компонента эквивалентны.
Классам доступны дополнительные возможности, о которых мы поговорим в следующих главах. Но пока что мы предпочтём функции за их краткость.
Как отрендерить компонент¶
Пока что мы только встречали React-элементы, представляющие собой DOM-теги:
1 |
|
Но элементы могут описывать и наши собственные компоненты:
1 |
|
Когда React встречает подобный элемент, он собирает все JSX-атрибуты в один объект и передаёт их нашему компоненту. Этот объект называется «пропсы» (props).
Например, этот компонент выведет «Привет, Алиса» на страницу:
1 2 3 4 5 |
|
Давайте разберём, что именно здесь происходит:
- Мы передаём React-элемент
<Welcome name="Алиса" />
вReactDOM.render()
. - React вызывает наш компонент
Welcome
с пропсами{name: 'Алиса'}
. - Наш компонент
Welcome
возвращает элемент<h1>Привет, Алиса</h1>
в качестве результата. - React DOM делает минимальные изменения в DOM, чтобы получилось
<h1>Привет, Алиса</h1>
.
Примечание: Всегда называйте компоненты с заглавной буквы.
Если компонент начинается с маленькой буквы, React принимает его за DOM-тег. Например,
<div />
это div-тег из HTML, а<Welcome />
это уже наш компонентWelcome
, который должен быть в области видимости.Чтобы узнать больше про это соглашение, прочитайте Углублённое изучение JSX.
Композиция компонентов¶
Компоненты могут ссылаться на другие компоненты в возвращённом ими дереве. Это позволяет нам использовать одну и ту же абстракцию — компоненты — на любом уровне нашего приложения. Неважно, пишем ли мы кнопку, форму или целый экран: все они, как правило, представляют собой компоненты в React-приложениях.
Например, компонент App
может отрендерить компонент Welcome
несколько раз:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
В приложениях, написанных на React с нуля, как правило, есть один компонент App
, который находится на самом верху. В случае, если вы переписываете существующее приложение на React, имеет смысл начать работу с маленького компонента типа Button
и постепенно двигаться «вверх» по иерархии.
Извлечение компонентов¶
Не бойтесь разбивать компоненты на части.
Допустим, у нас есть компонент Comment
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Этот компонент представляет собой комментарий в социальной сети. Его пропсы включают в себя author
(объект), text
(строка), и date
(дата).
С этим компонентом может быть не очень удобно работать из-за излишней вложенности. Мы также не можем повторно использовать его составные части. Давайте извлечём из него пару компонентов.
Для начала извлечём Avatar
:
1 2 3 4 5 6 7 8 9 |
|
Компоненту Avatar
незачем знать, что он рендерится внутри Comment
. Поэтому мы дали его пропу чуть менее конкретное имя — user
, а не author
.
Пропсы следует называть так, чтобы они имели смысл в первую очередь с точки зрения самого компонента, а уже во вторую тех компонентов, которые его рендерят.
Теперь можно немножко упростить наш Comment
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Следующим шагом извлечём компонент UserInfo
, который рендерит Avatar
рядом с именем пользователя:
1 2 3 4 5 6 7 8 |
|
Это позволит ещё сильнее упростить Comment
:
1 2 3 4 5 6 7 8 9 10 11 |
|
Извлечение компонентов может сначала показаться неблагодарной работой. Тем не менее, в больших приложениях очень полезно иметь палитру компонентов, которые можно многократно использовать. Если вы не уверены, извлекать компонент или нет, вот простое правило. Если какая-то часть интерфейса многократно в нём повторяется (Button
, Panel
, Avatar
) или сама по себе достаточно сложная (App
, FeedStory
, Comment
), имеет смысл её вынести в независимый компонент.
Пропсы можно только читать¶
Компонент никогда не должен что-то записывать в свои пропсы — вне зависимости от того, функциональный он или классовый.
Возьмём для примера функцию sum
:
1 2 3 |
|
Такие функции называют «чистыми», потому что они не меняют свои входные данные и предсказуемо возвращают один и тот же результат для одинаковых аргументов.
А вот пример нечистой функции — она записывает данные в свои же аргументы:
1 2 3 |
|
React достаточно гибкий, но есть одно правило, которое нельзя нарушать:
React-компоненты обязаны вести себя как чистые функции по отношению к своим пропсам.
Конечно, интерфейсы приложений обычно изменяются с течением времени. В следующей главе мы узнаем о том, что такое «состояние» компонента. Состояние даёт компонентам возможность реагировать на действия пользователя, ответы сервера и другие события, не нарушая чистоту компонента.