Навигация без навигационного пропса¶
Иногда требуется запустить навигационное действие из мест, где нет доступа к реквизиту navigation
, например, из промежуточного модуля Redux. В таких случаях для диспетчеризации навигационных действий можно использовать ref
на контейнер навигации.
Не используйте ref
, если:
- Вам нужно осуществлять навигацию изнутри компонента без необходимости передачи свойства
navigation
вниз, вместо этого смотритеuseNavigation
. Реквизитref
ведет себя по-другому, и многие вспомогательные методы, специфичные для экранов, недоступны. - Необходимо обрабатывать глубокие ссылки или универсальные ссылки. Это можно сделать с помощью
ref
. Дополнительную информацию о работе с глубокими ссылками см. в configuring links. - Необходима интеграция со сторонними библиотеками, такими как push-уведомления, branch и т.д. Смотрите Интеграции сторонних библиотек для глубокого связывания вместо этого.
Используйте ref
, если:
- Вы используете библиотеку управления состоянием, такую как Redux, где вам необходимо диспетчеризировать действия навигации из промежуточного ПО.
Обратите внимание, что обычно лучше запускать навигацию от действий пользователя, например, от нажатия кнопки, а не от промежуточного ПО Redux. Навигация по действиям пользователя делает приложение более отзывчивым и обеспечивает лучший UX. Поэтому подумайте об этом, прежде чем использовать ref
для навигации. ref
- это выход для сценариев, которые не могут быть реализованы с помощью существующих API, и должен использоваться только в редких случаях.
Использование¶
Вы можете получить доступ к корневому объекту навигации через ref
и передать его в RootNavigation
, который мы в дальнейшем будем использовать для навигации.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
На следующем шаге мы определяем RootNavigation
, который представляет собой простой модуль с функциями, диспетчеризирующими определенные пользователем навигационные действия.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Затем в любом из своих javascript-модулей импортируйте RootNavigation
и вызывайте экспортированные из него функции. Этот подход можно использовать вне React-компонентов, и, по сути, он также хорошо работает, если использовать его внутри них.
1 2 3 4 5 6 |
|
Кроме navigate
, можно добавить и другие действия навигации:
1 2 3 4 5 6 7 8 9 |
|
Обратите внимание, что для выполнения этого действия необходимо отрисовать стек навигаторов. Более подробную информацию можно найти в документации по вложению.
При написании тестов можно подражать функциям навигации и делать утверждения о том, что вызываются правильные функции с правильными параметрами.
Обработка инициализации¶
При использовании данного паттерна необходимо учитывать несколько моментов, чтобы избежать сбоев в работе навигации в приложении.
- Установка
ref
происходит только после рендеринга контейнера навигации, при работе с глубокими ссылками это может быть асинхронно - Навигатор должен быть отрендерен, чтобы иметь возможность обрабатывать действия,
ref
не будет готов без навигатора
Если попытаться выполнить навигацию без рендеринга навигатора или до того, как навигатор закончит монтироваться, то будет выведена ошибка и ничего не будет сделано. Поэтому необходимо добавить дополнительную проверку, чтобы решить, что делать, пока приложение не смонтируется.
Для примера рассмотрим следующий сценарий: у вас есть экран где-то в приложении, и этот экран отправляет действие redux по команде useEffect
/componentDidMount
. Вы слушаете это действие в своем промежуточном ПО и пытаетесь выполнить навигацию, когда получаете его. Это приведет к ошибке, поскольку к этому моменту родительский навигатор еще не закончил монтирование и не готов. Родительский useEffect
/componentDidMount
всегда вызывается после дочернего useEffect
/componentDidMount
.
Чтобы избежать этого, можно использовать метод isReady()
, доступный на ref, как показано в примерах выше.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Если вы не уверены, что навигатор отображается, можно вызвать navigationRef.current.getRootState()
, и он вернет корректный объект состояния, если все навигаторы отображаются, в противном случае он вернет undefined
.