[Перевод] Обмен данными между React-компонентами с использованием библиотеки RxJS
Перед вами перевод статьи Chidume Nnamdi, опубликованной на blog.bitsrc.io. Перевод публикуется с разрешения автора.
Появление библиотеки RxJS открыло массу новых возможностей в мире JS. Цель RxJS — достигать многого, используя небольшое количество кода. Прочитав эту статью, вы узнаете, как осуществлять обмен данными между компонентами приложения на React, применяя возможности RxJS.
Совет: используйте Bit для организации React-компонентов и обмена ими. Это позволит вашей команде быстрее разрабатывать свои приложения. Просто попробуйте.
React Components Collection
Redux
Обмен данными между несвязанными React-компонентами — это то, ради чего были созданы библиотеки управления состояниями. Существует множество шаблонов для управления состояниями, но наиболее известны два: Flux и Redux.
Redux популярен из-за своей простоты и использования чистых функций. Ведь благодаря им можно не сомневаться, что применение редьюсеров не приведет к каким-то побочным эффектам.
Работая с Redux, первым делом мы создаем централизованное хранилище данных:
Далее связываем компоненты с этим хранилищем и при желании обновляем или удаляем состояние. Любые изменения, внесенные в хранилище, будут отражены в компонентах, связанных с ним. Таким образом, поток данных распространяется на все компоненты, независимо от степени их вложенности. Компонент, находящийся на энном уровне иерархической структуры, способен передавать данные компоненту самого высокого уровня. Последний, в свою очередь, может передавать данные компоненту 21 уровня.
RxJS
С появлением RxJS использовать библиотеки управления состояниями стало гораздо проще. Многим понравился паттерн «Наблюдатель» (Observer), предоставляемый RxJS.
Мы просто создаем поток Observable
и даем возможность всем компонентам прослушивать его. Если какой-то компонент добавляется к потоку, прослушивающие (или «подписанные») компоненты реагируют на обновление DOM.
Установка
Создаем приложение на React, используя create-react-app
. Если у вас нет create-react-app
, то сперва установите его глобально:
npm i create-react-app -g
Далее генерируем проект в React:
create-react-app react-prj
Переходим в директорию:
cd react-prj
Устанавливаем библиотеку rxjs:
npm i rxjs
У нас должен появиться файл, создающий новый экземпляр BehaviourSubject
.
Почему мы используем BehaviorSubject?
BehaviorSubject
— это один из Subject в библиотеке RxJS. Будучи дочерним компонентом Subject, BehaviorSubject
позволяет множеству наблюдателей прослушивать поток, а также делает массовую рассылку событий этим наблюдателям. BehaviorSubject
сохраняет последнее значение и передает его всем новым подписанным компонентам.
Таким образом, BehaviorSubject
:
- Позволяет осуществлять массовую рассылку.
- Хранит последние значения, опубликованные подписчиками, и делает массовую рассылку этих значений.
В папке src находится файл messageService.js
, экспортирующий подписчику экземпляр BehaviorSubject
и объект messageService
. Объект-подписчик создается в начале файла — так он доступен для любого импортирующего компонента. У объекта messageService
имеется функция отправки, принимающая параметр msg
: в нем содержатся данные, которые нужны для передачи всем прослушивающим компонентам. В теле функции мы вызываем метод emit
. Он осуществляет массовую рассылку данных подписанным компонентам в объекте-подписчике.
Предположим, что у нас есть следующие компоненты:
- ConsumerA;
- ConsumerB;
- ProducerA;
- ProducerB.
В иерархической структуре они выглядят так:
Компонент приложения передает сообщение ProducerA и ConsumerB. ProducerA отправляет данные ConsumerA, а сообщение от ConsumerB попадает к ProducerB.
Компоненты ConsumerA и ConsumerB имеют индивидуальный счетчик состояния. В их методе componentDidMount
они подписаны на один и тот же поток subscriber
. Как только публикуется какое-либо событие, у обоих компонентов обновляется счетчик.
У ProducerA и ProducerB есть кнопки Increment Counter
и Decrement Counter
, которые при нажатии выдают 1
или -1
. Подписанные компоненты ConsumerA и ConsumerB подхватывают событие и запускают свои функции обратного вызова, обновляя значение счетчика состояния и DOM.
Посмотрим на иерархическую структуру еще раз:
ProducerB передает данные ConsumerA, хотя они абсолютно не связаны. ProducerA передает данные ConsumerB, не являясь его родительским компонентом. В этом вся суть RxJS: мы просто создали центральный узел потока событий и позволили компонентам прослушивать его. Когда какой-либо компонент генерирует события, прослушивающие компоненты тут же подхватывают их.
Поиграть с приложением можно на stackblitz: https://react-lwzp6e.stackblitz.io
Заключение
Итак, мы увидели, как можно осуществлять обмен данными между React-компонентами, применяя RxJS. Мы использовали BehaviourSubject
для создания централизованного потока данных, а затем позволили остальным компонентам подписаться на этот поток. Теперь, когда один из компонентов генерирует данные, прочие компоненты также получают их. Уровень компонентов в иерархической структуре неважен.
Если у вас есть вопросы относительно этой темы или вы хотите, чтобы я что-то добавил, исправил или удалил, напишите об этом в комментариях, в электронном письме или в личном сообщении.
Спасибо за внимание!