#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-navigation2. нет, потому что я использую 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
код не обрабатывает недопустимые пути, поэтому, я думаю, нам тоже нужно это реализовать, если это необходимо.