useNavigation hook failure outside NavigationContainer
0 reputation · 16 Sept 2023, 08:03 UTC
0 reputation · 16 Sept 2023, 08:03 UTC
The NavigationContainer component manages the navigation state and provides the context required for hooks like useNavigation. This architecture requires that any component accessing the navigation object must be a descendant of the container in the React component tree.
A design challenge arises when a component needs to trigger navigation actions but is positioned as a sibling to the NavigationContainer, or lives in a separate provider branch. Because the hook relies on the React Context API, calling it outside the provider's subtree fails, since no navigation context is available to that component.
What is the recommended architectural pattern for triggering navigation from components that cannot be nested within the NavigationContainer? Is there a documented method to expose a navigation reference to external components without breaking the context pattern?
First, create a ref and attach it to NavigationContainer:
import { NavigationContainer } from '@react-navigation/native';
import React from 'react';
const navigationRef = React.createRef();
export default function App() {
return (
{/* screens */}
);
}
Then, wherever you need to trigger navigation (even outside the container tree), import the ref and call:
if (navigationRef.current) {
navigationRef.current.navigate('ScreenName', { params });
} else {
// handle case when container not mounted yet
}
The useNavigation hook reads the navigation context provided by NavigationContainer. When a component is not a descendant of that container, the context is undefined, causing the hook to throw. A ref bypasses the context API and gives you an imperative reference to the navigation object once the container has mounted.
React.createRef() or useRef).NavigationContainer via the ref prop.If you still see the "Couldn't find a navigation object" warning after implementing the ref, please confirm the exact version of @react-navigation/native (and any stack navigator) you are using, as older versions (
Use comments to ask for clarification. Post a solution as an answer.
31,775 reputation · 16 Sept 2023, 12:55 UTC
In React Navigation 6 and later, the documented pattern is useNavigationContainerRef() instead of a bare React.createRef(). It returns a typed ref designed for the container, which improves inference for imperative navigate() calls. For v5 and earlier, a manually created useRef() passed to NavigationContainer was the standard approach.
Regardless of version, guard imperative calls with navigationRef.isReady() when available, or check that current is set before the container mounts. Module-level refs can also retain stale state under Fast Refresh, so consider creating the ref inside a wrapper component. Verify the installed version in package.json and test with a sibling button press after mount.