I am surprised that useLinkTo
and the like (useNavigation
) can only be used inside a Navigator Screen when all they really should need is the navigation context set-up by the NavigationContainer
.
Because my scenario is a notification system that wraps the whole app whose notifications should be able to link to other parts in the app.
<NavigationContainer linking={linking}>
<Notifications>
<RootStack/>
</Notifications>
</NavigationContainer>
Now that it sits outside the RootStack
hooks like useLinkTo
, useNavigation
do not work and complain about a missing context:
"Couldn't find a navigation object. Is your component inside a screen in a navigator?"
Is there a work-around for deep linking using the bare bone NavigationContainer (ref) maybe?
I tried to move the Notifications
provider inside RootStack
but that does not help.
In the documentation, there is a way mentioned for achieving this for useNavigation
, i.e Navigating without the navigation prop.
Basically, what we do is assign the navigation container to an external ref, and then use that ref to navigate while outside the RootStack
.
In file /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 });
Edit: More functions for ref can be found here: https://reactnavigation.org/docs/navigation-container
Then in your code,
import {navigationRef} from '/project/Navigation/RootNavigation';
<NavigationContainer ref={navigationRef} linking={linking}>
<Notifications>
<RootStack/>
</Notifications>
</NavigationContainer>
Then, you can import the useRootNavigation
hook in your Notification component to navigate, goback.
For better explanation, you can refer https://reactnavigation.org/docs/navigating-without-navigation-prop.
However, this is not possible for useLinkTo
currently I guess.
I'm too searching for a way to use useLinkTo
like this. If anyone finds it, please let me know!
Edit2:
For replicating the behavior of useLinkTo
, I implemented the following by referring to source code for useLinkTo
:
In file /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,
});
Then, wherever we need to use useLinkTo, outside the navigation
const navigation = useRootNavigation(); // The hook defined in RootNavigation.js
someFunction(()=>{
navigation.linkTo(path, linking.config);
})
In your(mine as well) case, we'll have to specify the linking config, or the default behavior of deep linking will be used.