Способы передачи данных между компонентами в React
React имеет различные способы передачи данных между своими компонентами:Render props / props; Context; React-Redux / Redux.
97К открытий100К показов
В React есть несколько способов передачи данных между компонентами: Render props / props, Context, React-Redux / Redux.
В этой статье вы узнаете об этих способах подробно. В каждом из них вы научитесь добиваться двух вариантов взаимодействия:
- от родителя к наследнику;
- от наследника к родителю.
Render props / props
Один из самых простых способов передачи данных в компоненты — это props (свойства).
Что такое prop?
Как известно, разметка в компонентах рендерится так:
Это отобразится как C component
C фактически отображается в P, так как P является его родительским компонентом. Кроме того, P может отобразить C следующим образом:
P добавляет дополнительные свойства в тег элемента C. Это очень похоже на <div id="d1"> </div>
в HTML, где id
— это атрибут со значением “nnamdi”. Каждый элемент на самом деле является отдельным экземпляром класса HTMLElement
.
Тег <div>
анализируется движком рендеринга в браузере, и для каждого тега создаются экземпляры класса HTMLElement
. Все теги в HTML имеют соответствующий HTMLElement
:
Каждый HTML*Element
выше является подклассом HTMLElement
. Эти HTML*Element
имеют методы и свойства, которые можно использовать для манипулирования данными и рендеринга.
В случае выше будет создан HTMLDivElement
:
Имя атрибута будет установлено в объект props вот так:
и передастся классу компонента C с помощью React.
Таким образом, компонент C может получить доступ к значению name
в объекте props через props.name
.
React основан на JSX, поэтому разметка в P будет скомпилирована в таком виде:
Первый параметр — это элемент для рендеринга, а второй содержит атрибуты элемента (в виде объектного литерала). CreateElement
возвращает литерал, содержащий первый и второй параметры.
При рендеринге React проверяет, является ли этот литерал на самом деле элементом или же классом. Если это класс, React создаёт его экземпляр, используя ключевое слово new, затем передает этот экземпляр в объект props и вызывает метод render.
Приведённый выше код показывает, что фактически делает React для рендеринга компонента или элемента.
Примечание: фрагмент выше не полный, он нужен, чтобы продемонстрировать, как компоненты получают аргумент props.
Сначала проверяется, является ли objType
элементом или классом. Затем IS_ELEMENT(…)
проверяет список всех элементов HTML. Если objType
соответствует одному из них, то возвращается флаг true: значит objType
является элементом. Если IS_ELEMENT(…)
возвращает false, то, objType
должен быть компонентом класса, тогда он уничтожает props и экземпляр класса из objType
. Затем он создаёт новый экземпляр класса, используя ключевое слово new и передавая его в props.
Таким образом P удаётся отправить данные в C.
Но как C теперь может отправлять данные обратно в родительский класс P? Это делается с помощью render props.
Что такое render props? Это концепция, посредством которой функция может быть передана дочерним компонентам в качестве свойства (props). Строка, объект, число или массив могут быть переданы через props дочерним компонентам. Это реализовано следующим образом:
Здесь функция () => {log ("render props")}
передаётся компоненту C через свойство func. Затем компонент C может ссылаться на неё через func в аргументе props. Это функция выводит render props в консоли.
Итак, теперь вы знаете, что такое render props (или свойства для рендеринга). Давайте посмотрим, как дочерние компоненты могут использовать их для связи с родительскими.
Что происходит в этом фрагменте? У компонента P метод вывода связан с его экземпляром. bind(this)
говорит JS запустить функцию внутри области видимости класса, объекта или функции. Вывод здесь выполняется за пределами класса P, но он по-прежнему может ссылаться на все свойства и методы, определённые в P.
Таким образом, метод вывода передаётся в компонент класса C, чтобы получить аргумент props через свойство func.
К кнопке «Send To Parent» компонента C привязано событие onclick
, необходимое для вызова метода вывода, с переданным в него аргументом props через func. Так что теперь this.props.func
в C содержит метод вывода в классе P:
Предположим, кнопка «Send To Parent» нажата. Вызывается this.props.func
, ссылаясь на метод вывода в P, далее вызывается сам метод вывода. В консоли будет отображено следующее:
Теперь C успешно связался со своим родителем P. Можно изменить код, чтобы C отправлял данные в P.
В этом фрагменте кода в P добавляется состояние, которое содержит свойство count
. В C при нажатии кнопки «Send To Parent» генерируется случайное число и передаётся в this.props.func
. Метод вывода компонента P перехватывает значение из аргумента evt
и обновляет состояние count
полученным значением, вызывая this.setState(…)
.
Как вы видите, значение P отправилось из его дочернего элемента C.
Свойство Parent
можно изменить, передав функцию компоненту Child
и вызвав эту функцию внутри компонента Child
.
Props и render props — это одно и то же, но они имеют разные концепции. Render props в основном используется для разделения логики рендеринга между компонентами. Но в данном случае этот метод был использован для передачи данных от дочернего компонента к родительскому.
Context
Для большинства разработчиков передача props глубоко вложенным компонентам в дереве была бы утомительной. React предоставляет способ определять глобальные данные в одном месте и получать к ним доступ из любого места в приложении.
Context (контекст) как раз используется в React для обмена данными между глубоко вложенными компонентами.
В этом фрагменте есть три компонента в дереве: App -> P -> C -> Sub-C
. App отображает P, P отображает C, а C отображает Sub-C, который определён как context с именем ColorContext
. P заключён в ColorContext.Provider
, это обеспечивает доступ к данным, определённым в ColorContext
, всем дочерним компонентам P.
Дочерние компоненты могут получить доступ к данным, определённым в ColorContext
, выполнив {this.context}
.
Чтобы сообщить React о намерении передать context от родительского компонента остальным его дочерним элементам, нужно определить два атрибута в родительском классе:
childContextTypes,
getChildContext.
Чтобы извлечь контекст внутри дочернего компонента, нужно определить в нём contextTypes
.
Родительский компонент определяет context, который React использует для передачи данных глобально своим дочерним элементам.
Как теперь сделать так, чтобы дочерние элементы могли передавать данные своим родителям?
Дочерние компоненты могут изменять значение context, который будет отражаться во всех вложенных компонентах, включая и родительский компонент.
React-Redux/Redux
Это своего рода “ремейк” способа Context в React. Redux — это простая библиотека управления свойствами приложения, которая позволяет легко хранить эти свойства в одном месте и изменять их из любого места.
React-Redux был создан, чтобы сделать Redux легко совместимым с приложениями React.
Поскольку состояние определяется в одном месте, родительские компоненты могут устанавливать или обновлять его значение, а дочерние могут это фиксировать: связь Родитель-Наследник.
Аналогично дочерние компоненты могут устанавливать или обновлять значение состояния в хранилище, и оно также будет фиксироваться родительскими компонентами: связь Наследник-Родитель.
В этом фрагменте создаётся центральное хранилище, в котором содержится свойство count
. P может обновить это свойство и дочерний компонент C получит его. Дочерний компонент также может обновить свойство count
, и родительский компонент получит его.
Они могут подключиться к центральному хранилищу, объединившись в функцию connect(...)
, которая возвращает компонент высшего порядка.
Заключение
В этом материале вы увидели, как происходит взаимодействие между компонентами React и какими способами можно этого достичь:
- Родитель-наследник,
- Наследник-Родитель.
В первом разделе вы увидели использование props и render props, они работают с помощью HTML-подобных атрибутов. Context использует центральное хранилище, которое родитель и потомки могут как читать, так и обновлять. React-Redux и Redux делают то же самое, что и Context, компоненты выполняют чтение/запись из центрального хранилища.
Для дальнейшего освоения React вам может быть полезен данный материал.
97К открытий100К показов