React Navigation: Accessing the navigation state from above

How we reached the navigation object outside the scope of the navigation container

James Chen
2 min readJul 12, 2022

If you’re new to react navigation, it’s a library available for react native mobile applications that allows you to manage how you navigate through screens on your app. You can even store the user’s navigation history in an easily accessible state. The way it’s generally set up is to create a stack navigator. And inside the Navigation Container, you can place Screens which inherit a navigation state that holds methods as well as information about the route that the user has taken to get there.

The problem

In our mobile app, we wanted to give our custom navigation bar an animation as you swap between pages. The way we originally built the app was to render the nav bar within each Screen component. However, by having the nav bar render inside each Screen, it would be hard to implement a smooth transition animation between pages. Instead of displaying an animation when changing screens, the nav bar would be re-rendered. One way to address this issue, is to bring the nav bar out of each Screen and have it sit outside, side by side to its container (Navigation container). This way, the nav bar will not be re-rendered as you swap screens.

But the nav bar still won’t work unless we have access to the navigation object that is typically housed inside of the Navigation container

A brief look through the docs gives us promising tools in useNavigation as well as NavigationContext. However if you try to use useNavigation and NavigationContext outside of the scope of NavigationContainer, you’ll get an error that says “Couldn’t find a navigation object. Is your component inside NavigationContainer?”

What then?

The solution

The way we solved this issue was with refs.

If you’re using a functional component, you simply declare the navRef using useRef() however since we used a class component to house our main container, we will have to pass in navRef as a prop into MainContainer where we can then access the navigation object.

export default function ActualContainer() {
const navRef = useRef()
return <MainContainer navRef={navRef}/>
}
class MainContainer extends Component {
render() {
return (
<>
<NavigationContainer ref={this.props.navRef}/>
<NavBar navRef={this.props.navRef}/>
</>
)
}
}

Even though our NavBar is not a child of the Navigation Container, it is able to access the navigation state through this workaround

Now that we can access the navigation state within NavBar we can simply call on its methods to start navigating the screens in the app. For our app, we used the resetRoot method to clear the navigation history because we didn’t need it. e.g.

navRef.resetRoot(…params)

Available methods:

navigate - direct screen to specified parameter
resetRoot - similar to replace, allows you to reset the route
getRootState - navigation state containing all nested
getCurrentRoute - returns route object of current screen
getCurrentOptions - returns options object of current screen
addListener - listen to changes in navigation state

More details here https://reactnavigation.org/docs/navigation-container/#methods-on-the-ref

--

--