Обновление: это решение больше не работает, поскольку React Native не включает стандартную библиотеку Node. Однако есть автономные модули, в которых реализован API EventEmitter. Рассмотрите возможность проверки eventemitter3 и tiny-emitter.
В последнее время я часто сталкивался с интересным паттерном при разработке своих приложений: вам нужно запустить определенный блок кода в компоненте A, реагируя на изменение в компоненте B. Например, при нажатии на компонент A компонент B должен анимировать имущество. Если оба являются братьями и сестрами (вы не можете передать функцию для обновления B из A) и учитывая, что вы не можете задействовать redux (поскольку мы говорим об анимации), вам нужно остановиться и подумать.
Я несколько раз видел, как реализовал следующую стратегию: когда компонент B изменяется, он обновляет логическое значение, которое определяет, должен ли выполняться блок кода в A. Когда логическое значение истинно, блок запускается, сразу же снова устанавливая для него значение false.
Это ужасная стратегия, добавляющая кучу ненужного кода. Понятно, что в этом случае мы хотим испускать события. А поскольку React Native зависит от Node.js, мы можем использовать фантастический EventEmitter от Node. Подробнее об этом можно прочитать здесь.
Во-первых, мы, очевидно, должны его импортировать:
import EventEmitter from 'events';
Теперь документация предлагает вам создать класс и учит тому, как делать что-то в Node. В React мы можем это упростить. В конструкторе:
constructor(props) { super(props); this._emitter = new EventEmitter(); }
Вы можете удалить слушателей по отдельности, но лучше всего удалить их все при размонтировании компонента:
componentWillUnmount() { this._emitter.removeAllListeners(); }
Теперь вы можете передать этот эмиттер через реквизит.
<ComponentA emitter={this._emitter} />
к любому дочернему компоненту, который должен генерировать или прослушивать события. Когда происходит изменение в компоненте A, он просто вызывает
this.props.emitter.emit('eventName');
В компоненте B мы должны установить слушателя как таковой:
componentWillMount() { this.props.emitter.addListener('eventName', () => { // this block of code executes when 'eventName' is emitted }); }
Заключение:
Узел EventEmitter - это мощный API, и я определенно рекомендую вам прочитать документацию, поскольку я лишь поверхностно рассмотрел, как это работает.
Понятно, что запускать все ваше приложение с настраиваемыми событиями - плохая практика и приводит к нечитаемому коду. Злоупотреблять этим точно не стоит. Но в некоторых случаях это может быть лучшим решением. Мне потребовалось несколько дней, чтобы почесать голову, поэтому я подумал, что, возможно, это поможет кому-то найти правильный путь в будущем. Если у вас есть исправления или предложения, оставляйте их в комментариях, я буду рад услышать ваши отзывы!