реакция-навигация использует ссылку на внешний экран, но внутри NavigationContainer

#react-native #react-navigation #react-navigation-v5

#react-native #реагирующая навигация #реагирующая навигация-v5

Вопрос:

Я удивлен, что useLinkTo и тому подобное ( useNavigation ) можно использовать только внутри экрана навигатора, когда все, что им действительно нужно, — это настройка контекста навигации с помощью NavigationContainer .

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

 <NavigationContainer linking={linking}>
  <Notifications>
    <RootStack/>
  </Notifications>
</NavigationContainer>
  

Теперь, когда он находится за пределами RootStack крючков, например useLinkTo , useNavigation не работает и жалуется на отсутствие контекста:

«Не удалось найти объект навигации. Находится ли ваш компонент внутри экрана в навигаторе? «

Возможно, есть обходной путь для глубокой компоновки с использованием простого NavigationContainer (ссылка)?

Я попытался переместить Notifications провайдера внутрь RootStack , но это не помогло.

Комментарии:

1. Вы пробовали использовать withNavigation ? reactnavigation.org/docs/1.x/with-navigation

2. нет, потому что я использую v5, а не v1

Ответ №1:

В документации упоминается способ достижения этого useNavigation , т.е. Для навигации без навигационного реквизита.

По сути, то, что мы делаем, это назначаем навигационный контейнер внешней ссылке, а затем используем эту ссылку для навигации, находясь вне RootStack .

В файле /project/Navigation/RootNavigation.js

 import { createRef } from 'react';

export const navigationRef = createRef();

export function navigate(name, params) {
  navigationRef.current?.navigate(name, params);
}

export function goBack() {
  navigationRef.current?.goBack();
}

export default useRootNavigation = () => ({ navigationRef, navigate, goBack });
  

Редактировать: дополнительные функции для ссылки можно найти здесь: https://reactnavigation.org/docs/navigation-container

Затем в вашем коде,

 import {navigationRef} from '/project/Navigation/RootNavigation';

<NavigationContainer ref={navigationRef} linking={linking}>
  <Notifications>
    <RootStack/>
  </Notifications>
</NavigationContainer> 

  

Затем вы можете импортировать useRootNavigation перехват в свой компонент уведомлений для навигации, возврата.
Для лучшего объяснения вы можете обратиться https://reactnavigation.org/docs/navigating-without-navigation-prop .

Однако, useLinkTo я думаю, в настоящее время это невозможно. Я слишком ищу способ использовать useLinkTo подобное. Если кто-нибудь найдет это, пожалуйста, дайте мне знать!

Правка2:

Для воспроизведения поведения useLinkTo я реализовал следующее, обратившись к исходному коду для useLinkTo :

В файле /project/Navigation/RootNavigation.js

 import { getActionFromState, getStateFromPath } from '@react-navigation/native';

/**
* Previous code
*/

export function dispatch(action) {
  navigationRef.current?.dispatch(action);
}

export function linkTo(path, config = null) {
  var state = getStateFromPath(path, config);
  var action = getActionFromState(state);
  if (action !== undefined) {
    dispatch(action);
  }
}

export default useRootNavigation = () => ({
  navigationRef,
  navigate,
  goBack,
  dispatch,
  linkTo,
});
  

Затем, везде, где нам нужно использовать useLinkTo, за пределами навигации

   const navigation = useRootNavigation(); // The hook defined in RootNavigation.js

  someFunction(()=>{
    navigation.linkTo(path, linking.config);
  })

  

В вашем (моем тоже) случае нам нужно будет указать конфигурацию компоновки, иначе будет использоваться поведение глубокой компоновки по умолчанию.

Комментарии:

1. Спасибо! Я вижу, что ссылка по умолчанию выполняет немного больший переход вверх по дереву ссылок при создании действия навигации. Вы уверены, что ваш код работает должным образом?

2. @philk да, это сработало для меня, и оно должно работать так, как ожидалось, поскольку используемая ссылка является корнем всех навигаторов; таким образом, устраняется необходимость обхода вверх.

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