Компоненты и пропсы¶
Компоненты позволяют разбить интерфейс на независимые части, про которые легко думать в отдельности. Их можно складывать вместе и использовать несколько раз. На этой странице мы ознакомимся с самой идеей компонентов.
Во многом компоненты ведут себя как обычные функции 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-компоненты обязаны вести себя как чистые функции по отношению к своим пропсам.
Конечно, интерфейсы приложений обычно изменяются с течением времени. В следующей главе мы узнаем о том, что такое «состояние» компонента. Состояние даёт компонентам возможность реагировать на действия пользователя, ответы сервера и другие события, не нарушая чистоту компонента.