для чего используется props в react компонентах
Рендер-пропсы
Термин «рендер-проп» относится к возможности компонентов React разделять код между собой с помощью пропа, значение которого является функцией.
Компонент с рендер-пропом берёт функцию, которая возвращает React-элемент, и вызывает её вместо реализации собственного рендера.
Такой подход, в частности, применяется в библиотеках React Router, Downshift и Formik.
В этой статье мы покажем, чем полезны и как писать рендер-пропсы.
Использование рендер-пропа для сквозных задач
Компоненты — это основа повторного использования кода в React. Однако бывает неочевидно, как сделать, чтобы одни компоненты разделяли своё инкапсулированное состояние или поведение с другими компонентами, заинтересованными в таком же состоянии или поведении.
Например, следующий компонент отслеживает положение мыши в приложении:
Когда курсор перемещается по экрану, компонент отображает координаты (x, y) внутри
Возникает вопрос: как мы можем повторно использовать это поведение в другом компоненте? То есть если другому компоненту необходимо знать о позиции курсора, можем ли мы как-то инкапсулировать это поведение, чтобы затем легко использовать его в этом компоненте?
Теперь компонент инкапсулирует всё поведение, связанное с обработкой событий mousemove и хранением позиций курсора (x, y), но пока не обеспечивает повторного использования.
Для начала вы можете отрендерить внутри метода render компонента следующим образом:
Этот подход будет работать для конкретного случая, но мы не достигли основной цели — инкапсулировать поведение с возможностью повторного использования. Теперь, каждый раз когда мы хотим получить позицию мыши для разных случаев, нам требуется создавать новый компонент (т. е. другой экземпляр ), который рендерит что-то специально для этого случая.
Вот здесь рендер-проп нам и понадобится: вместо явного указания внутри компонента, и трудозатратных изменений на выводе рендера, мы предоставляем функцию в качестве пропа, с которой мы используем динамическое определение того, что нужно передавать в рендер-проп.
Иными словами, рендер-проп — функция, которая сообщает компоненту что необходимо рендерить.
Эта техника позволяет сделать легко портируемым поведение, которое мы хотим повторно использовать. Для этого следует отрендерить компонент с помощью рендер-пропа, который сообщит, где отрендерить курсор с текущим положением (x, y).
Таким образом, рендер-пропы позволяют реализовать любой из описанных выше паттернов.
Использование пропсов, отличных от render (как название передаваемого свойства)
И запомните, проп children не обязательно именовать в списке «атрибутов» вашего JSX-элемента. Вместо этого, вы можете поместить его прямо внутрь элемента!
Эту технику можно увидеть в действии в API библиотеки react-motion.
Поскольку этот метод не совсем обычен, вы, вероятно, захотите явно указать, что children должен быть функцией в вашем propTypes при разработке такого API.
Будьте осторожны при использовании рендер-проп вместе с React.PureComponent
Чтобы решить эту проблему, вы можете определить проп как метод экземпляра, например так:
Компоненты и пропсы¶
Компоненты позволяют разбить интерфейс на независимые части, про которые легко думать в отдельности. Их можно складывать вместе и использовать несколько раз. На этой странице мы ознакомимся с самой идеей компонентов.
Во многом компоненты ведут себя как обычные функции JavaScript. Они принимают произвольные входные данные (так называемые «пропсы») и возвращают React-элементы, описывающие, что мы хотим увидеть на экране.
Функциональные и классовые компоненты¶
Проще всего объявить React-компонент как функцию:
Эта функция — компонент, потому что она получает данные в одном объекте («пропсы») в качестве параметра и возвращает React-элемент. Мы будем называть такие компоненты «функциональными», так как они буквально являются функциями.
Ещё компоненты можно определять как классы ES6:
С точки зрения React, эти два компонента эквивалентны.
Классам доступны дополнительные возможности, о которых мы поговорим в следующих главах. Но пока что мы предпочтём функции за их краткость.
Как отрендерить компонент¶
Пока что мы только встречали React-элементы, представляющие собой DOM-теги:
Но элементы могут описывать и наши собственные компоненты:
Когда React встречает подобный элемент, он собирает все JSX-атрибуты в один объект и передаёт их нашему компоненту. Этот объект называется «пропсы» (props).
Например, этот компонент выведет «Привет, Алиса» на страницу:
Давайте разберём, что именно здесь происходит:
Привет, Алиса
Привет, Алиса
Примечание: Всегда называйте компоненты с заглавной буквы.
Если компонент начинается с маленькой буквы, React принимает его за DOM-тег. Например,
Чтобы узнать больше про это соглашение, прочитайте Углублённое изучение JSX.
Композиция компонентов¶
Компоненты могут ссылаться на другие компоненты в возвращённом ими дереве. Это позволяет нам использовать одну и ту же абстракцию — компоненты — на любом уровне нашего приложения. Неважно, пишем ли мы кнопку, форму или целый экран: все они, как правило, представляют собой компоненты в React-приложениях.
Например, компонент App может отрендерить компонент Welcome несколько раз:
Извлечение компонентов¶
Не бойтесь разбивать компоненты на части.
Допустим, у нас есть компонент Comment :
Этот компонент представляет собой комментарий в социальной сети. Его пропсы включают в себя author (объект), text (строка), и date (дата).
С этим компонентом может быть не очень удобно работать из-за излишней вложенности. Мы также не можем повторно использовать его составные части. Давайте извлечём из него пару компонентов.
Для начала извлечём Avatar :
Пропсы следует называть так, чтобы они имели смысл в первую очередь с точки зрения самого компонента, а уже во вторую тех компонентов, которые его рендерят.
Теперь можно немножко упростить наш Comment :
Это позволит ещё сильнее упростить Comment :
Пропсы можно только читать¶
Компонент никогда не должен что-то записывать в свои пропсы — вне зависимости от того, функциональный он или классовый.
Возьмём для примера функцию sum :
Такие функции называют «чистыми», потому что они не меняют свои входные данные и предсказуемо возвращают один и тот же результат для одинаковых аргументов.
А вот пример нечистой функции — она записывает данные в свои же аргументы:
React достаточно гибкий, но есть одно правило, которое нельзя нарушать:
React-компоненты обязаны вести себя как чистые функции по отношению к своим пропсам.
Конечно, интерфейсы приложений обычно изменяются с течением времени. В следующей главе мы узнаем о том, что такое «состояние» компонента. Состояние даёт компонентам возможность реагировать на действия пользователя, ответы сервера и другие события, не нарушая чистоту компонента.
Компоненты и свойства
Компоненты позволяют разделить пользовательский интерфейс на независимые, повторно используемые части и работать с каждой из частей отдельно. На этой странице представлено введение в идею компонентов. Здесь вы можете найти подробный справочник API по компоненту.
Концептуально компоненты похожи на функции JavaScript. Они принимают произвольные входные данные (называемые «props» или свойствами) и возвращают React-элементы, описывающие, что должно появиться на экране.
Функциональные и классовые компоненты
Самый простой способ определить компонент — написать JavaScript-функцию:
Данная функция — корректный компонент React, потому что он принимает один аргумент-объект «props» (который обозначает свойства) с данными и возвращает элемент React. Такие компоненты мы называем «функциональными», потому что они являются буквально функциями JavaScript.
Вы также можете использовать класс из ES6 для определения компонента:
Два вышеуказанных компонента эквивалентны с точки зрения React.
У классов есть дополнительные возможности, которые мы обсудим в следующих разделах. До этого момента мы будем использовать функциональные компоненты из-за их краткости.
Раньше мы сталкивались только с элементами React, представляющие DOM-теги:
Однако элементы также могут быть пользовательскими компонентами:
Когда React видит элемент, представляющий пользовательский компонент, он передаёт JSX-атрибуты этому компоненту в виде единственного объекта. Мы называем этот объект «props».
Например, этот код отображает «Привет, Сара» на странице:
Давайте посмотрим, что происходит в этом примере:
Hello, Sara
Hello, Sara
Примечание: Всегда именуйте компоненты с заглавной буквы.
React обрабатывает компоненты, начинающиеся со строчных букв, как DOM-теги. Например,
Вы можете больше узнать о причинах, лежащих в основе этого соглашения здесь.
Компоненты могут ссылаться на другие компоненты в своём выводе. Это позволяет использовать одну и ту же абстракцию компонента для любого уровня детализации. Кнопка, форма, диалоговое окно, экран: в приложениях React все они обычно являются компонентами.
Не бойтесь разделять компоненты на более мелкие компоненты.
Например, рассмотрим этот компонент Comment :
Он принимает author (объект), text (строка) и date (дата) в качестве свойств и описывает комментарий на сайте социальных сетей.
Этот компонент может быть сложно изменить из-за вложенности, а также трудно повторно использовать отдельные его части. Давайте извлечём из него несколько компонентов.
Сначала мы извлечём Avatar :
Мы рекомендуем называть свойства объекта props с точки зрения самого компонента, а не контекста, в котором он используется.
Теперь мы можем чуть-чуть упростить Comment :
Это позволяет нам упростить Comment ещё больше:
Свойства объекта props доступны только для чтения
Независимо от того, объявляете ли компонент как функцию или класс, он не должен изменять свои свойства. Рассмотрим эту функцию sum :
Такие функции называются «чистыми», потому что они не пытаются изменить свои аргументы и всегда возвращают один и тот же результат для одних и тех же входных данных.
Напротив, функция ниже — не чистая, потому что она изменяет свои входные данные:
React довольно гибкий, но имеет одно строгое правило:
Все React-компоненты должны вести себя как чистые функции в плане своих свойств.
Конечно, пользовательские интерфейсы приложений динамичны и меняются со временем. В следующем разделе мы представим новую концепцию «состояние». Состояние позволяет компонентам React изменять свой вывод с течением времени в ответ на действия пользователя, сетевые ответы и что-либо ещё без нарушения правила выше.
React.Component
Эта страница содержит подробный справочник API для определения класса компонента React. Предполагается, что вы знакомы с фундаментальными концепциями React, такими как компоненты и свойства, а также состояние и жизненный цикл. Если вы этого не сделали, сначала прочитайте их.
React позволяет вам определять компоненты как классы или функции. В настоящее время компоненты, определённые как классы, предоставляют больше возможнотей, которые подробно описаны на этой странице. Чтобы определить класс компонента React, вам необходимо расширить React.Component :
Мы настоятельно не рекомендуем создавать собственные классы базовых компонентов. В React-компонентах повторное использование кода в основном достигается с помощью композиции, а не наследования.
React не заставляет вас использовать синтаксис класса ES6. Если вы предпочитаете избегать его использования, вы можете установить пакет create-react-class или аналогичную пользовательскую абстракцию. Посмотрите на Использование React без ES6, чтобы узнать больше.
Жизненный цикл компонента
Каждый компонент имеет несколько «методов жизненного цикла», которые вы можете переопределить для выполнения кода в определенное время в процессе. Вы можете использовать эту диаграмму жизненного цикла в качестве шпаргалки. В приведённом ниже списке обычно используемые методы жизненного цикла выделены полужирным шрифтом. Остальные из них существуют для относительно редких случаев использования.
Эти методы вызывают в следующем порядке, когда экземпляр компонента создаётся и добавляется в DOM:
Эти методы считаются устаревшими, и вам следует избегать их использование в новом коде:
Обновление может быть вызвано изменениями в свойствах или состоянии. Эти методы вызываются в следующем порядке, когда компонент повторно отрисовывается:
Эти методы считаются устаревшими, и вам следует избегать их использование в новом коде:
Этот метод вызывается, когда компонент удаляется из DOM:
Этот метод вызывается при возникновении ошибки во время отрисовки, в методе жизненного цикла или в конструкторе любого дочернего компонента.
Каждый компонент также предоставляет некоторые другие методы API:
Общеиспользуемые методы жизненного цикла
Методы в этом разделе охватывают подавляющее большинство случаев использования, с которыми вы столкнётесь при создании React-компонентов. Для наглядной иллюстрации ознакомьтесь с этой диаграммой жизненного цикла.
Метод render() — единственный обязательный методов в классовом компоненте.
При вызове он должен проверять this.props и this.state и возвращать один из следующих типов:
Функция render() должна быть чистой, что означает, что она не изменяет состояние компонента, она возвращает один и тот же результат при каждом вызове и не взаимодействует напрямую с браузером.
Если вам нужно взаимодействовать с браузером, выполняйте все необходимые операции в componentDidMount() или других методах жизненного цикла. Сохранение render() чистым делает компонент легче для понимания.
Если вы не инициализируете состояние и не привязываете методы, вам не нужно реализовывать конструктор в вашем React-компоненте.
Конструктор для компонента React вызывается до того, как будет примонтирован. При реализации конструктора подкласса React.Component вы должны называть super(props) перед любым другим выражением. В противном случае this.props не будет определен в конструкторе, что может привести к багам.
Как правило, в React конструкторы используются только для двух целей:
** Избегайте копирования свойств в состояние! Это распространённая ошибка:**
componentDidMount() вызывается сразу после монтирования компонента (вставлено в DOM-дерево). Инициализация, требующая DOM-узлов, должна быть здесь. Если вам нужно загружать данные с удалённой конечной точки (endpoint), это хорошее место для создания экземпляра сетевого запроса.
componentDidUpdate() вызывается сразу после обновления. Этот метод не вызывается при первоначальной отрисовке.
Используйте данный метод как возможность работать с DOM при обновлении компонента. Это также хорошее место для выполнения сетевых запросов, если вы сравниваете текущие свойства с предыдущими свойствами (например, не нужно делать сетевой запрос, если свойство не изменилось).
Редко используемые методы жизненного цикла
Методы в этом разделе соответствуют малораспространённым случаям использования. Они удобны время от времени, но большинство ваших компонентов, вероятно, не нуждаются ни в одном из них. Вы можете увидеть большинство приведенных ниже методов на этой диаграмме жизненного цикла, если наверху страницы вы нажмете на чекбокс «Show less common lifecycles».
Вывод состояния приводит к подробному коду и затрудняет понимание ваших компонентов. Убедитесь, что вы хорошо знакомы с более простыми альтернативами:
Если вы хотите повторно вычислить некоторые данные только при изменении свойств, используйте помощник мемоизации вместо этого.
Этот метод не имеет доступа к экземпляру компонента. Если вы хотите, то можете повторно использовать код между getDerivedStateFromProps() и другими методами класса, извлекая чистые функции свойства и состояния компонента вне определения класса.
Этот не распространённый вариант использования, но он может быть в пользовательских интерфейсах, таких как цепочка сообщений в чатах, который должен обрабатывать позицию прокрутки особым образом.
Должно быть возвращено значение снимка (или null ).
Граница ошибок — это React-компоненты, которые перехватывают ошибки JavaScript в любом месте их дочернего дерева компонентов, логируют эти ошибки и отображают резервный интерфейс вместо разрушенного дерева компонентов. Граница ошибок отлавливают ошибки при отрисовке, в методах жизненного цикла и в конструкторах всего дерева под ними.
Классовый компонент становится границей ошибки, если он определяет этот метод жизненного цикла. Вызов setState() в нём позволяет зафиксировать необработанную JavaScript-ошибку в приведённом ниже дереве и отобразить резервный интерфейс. Используйте только граница ошибок для восстановления от неожиданных исключений; не пытайтесь использовать их для управления потоком.
Для получения дополнительной информации смотрите раздел Обработка ошибок в React 16.
Граница ошибок перехватывают только ошибки в компонентах ниже в их дереве. Граница ошибки не может поймать ошибку внутри себя.
This lifecycle is invoked after an error has been thrown by a descendant component. It receives the error that was thrown as a parameter and should return a value to update state.
getDerivedStateFromError() is called during the “render” phase, so side-effects are not permitted. For those use cases, use componentDidCatch() instead.
Устаревшие методы жизненного цикла
The lifecycle methods below are marked as “legacy”. They still work, but we don’t recommend using them in the new code. You can learn more about migrating away from legacy lifecycle methods in this blog post.
Это единственный хук жизненного цикла, вызываемый серверной отрисовкой.
Использование этого метода жизненного цикла часто приводит к ошибкам и несоответствиям.
UNSAFE_componentWillReceiveProps() вызывается до того, как смонтированный компонент получит новые свойства. Если вам нужно обновить состояние в ответ на изменения свойства (например, для его сброса), вы можете сравнить this.props и nextProps и выполнить переходы состояния с помощью this.setState() в этом методе.
Обратите внимание, что если родительский компонент заставляет ваш компонент повторно отрисовываться, этот метод будет вызываться, даже если свойства не изменились. Убедитесь в том, что сравниваете текущие и следующие значения, если вы только хотите обрабатывать изменения.
UNSAFE_componentWillUpdate() вызывается непосредственно перед отрисовкой при получении новых свойств или состояния. Используйте это как возможность выполнить подготовку до того, как произойдет обновление. Этот метод не вызывается при первоначальной отрисовке.
UNSAFE_componentWillUpdate() не будет вызываться, если shouldComponentUpdate() возвращает false.
В отличие от описанных выше методов жизненного цикла (которые React вызывает за вас), ниже приведены методы, которые вы можете вызывать из своих компонентов.
setState () ставит в очередь изменения в состояние компонента и указывает React, что этот компонент и его дочерние элементы должны быть повторно отрисованы с обновлённым состоянием. Это основной метод, который вы будете использовать для обновления пользовательского интерфейса в ответ на обработчики событий и ответы сервера.
Думайте о setState() как о запросе, а не как о команде немедленного действия для обновления компонента. Для лучшей очевидной производительности React может задержать выполнение, а затем обновить несколько компонентов за один проход. React не гарантирует незамедлительного применения изменений в состоянии.
Первый аргумент — это функция updater со следующим определением:
Второй параметр setState() — необязательный колбэк, вызываемый после завершения работы setState и далее компонент будет повторно отрисован. Обычно вместо этого мы рекомендуем использовать componentDidUpdate() для подобной логики.
Вы можете опционально передать объект в качестве первого аргумента setState() вместо функции:
Следующий фрагмент кода выполняет поверхностное объединение stateChange в новое состояние, например, чтобы скорректировать количество товаров в корзине:
Эта форма записи setState() также асинхронна, и несколько вызовов в течение одного цикла могут быть объединены (сгруппированы) вместе. Например, если вы пытаетесь увеличить количество элементов более одного раза в одном цикле, результат будет эквивалентным следующему ниже коду:
Последующие вызовы будут переопределять значения из предыдущих вызовов в том же самом цикле, поэтому количество будет увеличиваться только один раз. Если следующее состояние зависит от предыдущего состояния, мы рекомендуем использовать форму функции для обновления, т.е. следующим образом:
Для более подробной информации смотрите:
Если props.color не предоставлен, по умолчанию будет установлено значение ‘синий’ :
Строка displayName используется для отладочных сообщений. Обычно вам не нужно явно указывать её, поскольку по умолчанию предполагается имя функции или класса, который определяет компонент. Возможно, вы захотите установить его явно, если хотите отобразить другое имя для целей отладки или когда вы создаёте компонент высшего порядка, смотрите раздел Обтекание отображаемого имени для легкой отладки для получения подробной информации.
this.props содержит свойства, которые были определены вызывающим элементом этого компонента. Смотрите раздел Компоненты и реквизит для ознакомления со свойствами.
В частности, this.props.children — специальное свойство, обычно определяемое дочерними тегами в JSX-выражении, а не в самом теге.
Состояние содержит данные, конкретные для этого компонента, которые могут измениться со временем. Состояние определёно пользователем, и оно должно быть простым объектом JavaScript.
Если какое-либо значение не используется для отрисовки или потока данных (например, идентификатор таймера), вам не нужно вставлять его в состояние. Такие значения могут быть определены как поля экземпляра компонента.
Дополнительную информацию о состоянии смотрите в разделе Состояние и жизненный цикл.
Components and Props
Components let you split the UI into independent, reusable pieces, and think about each piece in isolation. This page provides an introduction to the idea of components. You can find a detailed component API reference here.
Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called “props”) and return React elements describing what should appear on the screen.
Function and Class Components
The simplest way to define a component is to write a JavaScript function:
This function is a valid React component because it accepts a single “props” (which stands for properties) object argument with data and returns a React element. We call such components “function components” because they are literally JavaScript functions.
You can also use an ES6 class to define a component:
The above two components are equivalent from React’s point of view.
Function and Class components both have some additional features that we will discuss in the next sections.
Rendering a Component
Previously, we only encountered React elements that represent DOM tags:
However, elements can also represent user-defined components:
When React sees an element representing a user-defined component, it passes JSX attributes and children to this component as a single object. We call this object “props”.
For example, this code renders “Hello, Sara” on the page:
Let’s recap what happens in this example:
Hello, Sara
Hello, Sara
Note: Always start component names with a capital letter.
React treats components starting with lowercase letters as DOM tags. For example,
To learn more about the reasoning behind this convention, please read JSX In Depth.
Components can refer to other components in their output. This lets us use the same component abstraction for any level of detail. A button, a form, a dialog, a screen: in React apps, all those are commonly expressed as components.
For example, we can create an App component that renders Welcome many times:
Typically, new React apps have a single App component at the very top. However, if you integrate React into an existing app, you might start bottom-up with a small component like Button and gradually work your way to the top of the view hierarchy.
Don’t be afraid to split components into smaller components.
For example, consider this Comment component:
It accepts author (an object), text (a string), and date (a date) as props, and describes a comment on a social media website.
This component can be tricky to change because of all the nesting, and it is also hard to reuse individual parts of it. Let’s extract a few components from it.
First, we will extract Avatar :
We recommend naming props from the component’s own point of view rather than the context in which it is being used.
We can now simplify Comment a tiny bit:
Next, we will extract a UserInfo component that renders an Avatar next to the user’s name:
This lets us simplify Comment even further:
Props are Read-Only
Whether you declare a component as a function or a class, it must never modify its own props. Consider this sum function:
Such functions are called “pure” because they do not attempt to change their inputs, and always return the same result for the same inputs.
In contrast, this function is impure because it changes its own input:
React is pretty flexible but it has a single strict rule:
All React components must act like pure functions with respect to their props.
Of course, application UIs are dynamic and change over time. In the next section, we will introduce a new concept of “state”. State allows React components to change their output over time in response to user actions, network responses, and anything else, without violating this rule.