Предоставьте свои навигаторы React Navigation для простого обмена состоянием между любыми дочерними экранами в React Native.

Обновление 1/7/2020:

Обратите внимание, что это было написано с помощью Expo 32.x и React-Navigation 3.x. Я считаю, что применимы те же общие идеи, но из-за изменений (в частности, модульности) в пакетах написанный код не будет точно таким же.

Обновление 14.06.2021:

Ссылки React Native обновлены и указывают на документацию 3.x.

В последнее время я использую React Navigation в своих проектах React Native, и мне это очень нравится. В нем есть все необходимые мне функции, и с ним можно легко работать прямо из коробки. Если вы здесь, то, вероятно, тоже работали с ним, поэтому я предполагаю, что у вас есть базовые рабочие знания как React Navigation, так и React Native.

Недавно я столкнулся с раздражающей проблемой, на решение которой мне потребовалось время, - с необходимостью разделения состояния между соответствующими экранами в навигаторе. В этом случае у меня был StackNavigator с несколькими экранами, на которых все работали с одними и теми же данными.

Это было проблемой, потому что React Navigation по умолчанию не предоставляет большую часть создаваемых вами навигаторов как компоненты, которые можно использовать непосредственно в разметке, поэтому нет очевидного способа передать объект состояния в качестве опоры для дочернего элемента. экраны. Базовая реализация React Navigation может выглядеть примерно так:

В приведенном выше примере MainTabNavigator является компонентом React, но явное отображение его является антипаттерном / распространенной ошибкой. По умолчанию единственный навигатор, который напрямую подвергается воздействию разметки, - это корневой компонент AppContainer, который отображается в App.js.

Так что, если вы хотите разделить какое-то состояние между всеми дочерними экранами вашего MainTabNavigator?

Вы можете управлять этим состоянием, где бы вы ни отображали свой AppContainer, но это может быть очень далеко от того места, где на самом деле находится ваш навигатор.

В качестве альтернативы вы можете добавить библиотеку управления состоянием, такую ​​как Redux или MobX, но это может быть излишним и / или внести ненужную сложность.

К счастью, есть третье решение - создать собственный навигатор. Пользовательский навигатор импортирует встроенный навигатор и отображает его как обычный компонент, к которому вы можете добавлять дополнительные свойства по мере необходимости.

Реализация настраиваемого навигатора на самом деле довольно проста, но детали были разбросаны по документации таким образом, что мне было сложно понять, что мне нужно делать.

Полный код этого проекта находится на GitHub. Это упрощенная версия приложения Tabs по умолчанию, созданного с помощью expo init через интерфейс командной строки Expo, и все, что оно делает, это отслеживает, сколько раз пользователь переключал вкладки.

Приведенные ниже шаги предполагают, что вы начали с базового приложения React Native с помощью React Navigation со структурой, подобной BasicReactNavigationSetup в приведенном выше фрагменте.

Шаг первый

Создайте собственный навигатор. По сути, этот компонент должен делать две вещи.

  1. Ему нужно назначить себе роутер.
  2. Ему необходимо импортировать и отобразить встроенный компонент навигатора.

Сначала давайте настроим router, чтобы сообщить React Navigation, как будет работать этот пользовательский навигатор.

Маршрутизаторы определяют состояние навигации компонента и позволяют разработчику определять пути и действия, которые могут быть обработаны. - Реагировать на навигацию

В MainTabNavigator уже есть TabRouter, и это то, что мы должны использовать для нашего настраиваемого навигатора. Все пути и действия уже определены, и он будет обеспечивать такое же поведение, как если бы мы использовали MainTabNavigator самостоятельно.

Во-вторых, нам нужно отобразить MainTabNavigation, убедившись, что он поддерживает доступ к свойству navigation.

В приведенном выше фрагменте мы фактически отключили наш объект MainTabNavigator от объекта React Navigations navigation, и наше приложение выдаст ошибку, если мы попытаемся его запустить. Мы можем исправить это, явно присвоив navigation MainTabNavigator

Если хотите, вы можете сделать то же самое, вместо этого заключив MainTabNavigator в withNavigation HOC.

Шаг второй

Настройте свое состояние и передайте несколько реквизитов.

Мы обновим настраиваемый навигатор, чтобы создать счетчик, который будет отслеживать, сколько раз были переключены вкладки, и метод, увеличивающий счетчик. Мы передадим оба этих параметра MainTabNavigator в качестве свойств, чтобы любой дочерний экран мог отображать счетчик и запускать приращение при переключении вкладок.

Проблема в том, что реквизиты нельзя назначать непосредственно MainTabNavigator. Чтобы они правильно передавались на экраны, они должны быть назначены через screenProps.

Шаг третий

К свойствам, назначенным через screenProps, теперь можно получить доступ с любого экрана, который является дочерним для MainTabNavigator.

Мы можем использовать их для создания базового компонента экрана, который будет отображать количество переключений вкладок и запускать функцию приращения при переходе на новый экран.

Спасибо!



Надеюсь, вы нашли эту рецензию полезной. Это первая публикация, которую я здесь опубликовал, и я буду приветствовать любые мысли по поводу содержания или предложения по улучшению!