React Navigation: Disable Android hardware back button on specific screen

Hristo Eftimov
Dev Labs
Published in
3 min readFeb 28, 2018

--

ReactNavigation is a powerful library for navigation between the screens of your React Native application.

The learning curve is a little bit hard and confusing but once you understand how it works you can build really complex and nested navigation structures for your project.

Like it usually happens when using a new library, I soon faced a strange issue and I started a long and demotivating research about how to fix it. Of course, my project is not simple, the opposite — it’s complex and makes the research harder.

So, let me share my problem:

The structure:

Here is one simple situation in my application: a have an Auth screen with login and then the main screen with a tab navigation.

The issue:

When I switch between the main screens: events, event details, settings, etc. I am using the Android’s native back button to leave the current screen.

Ok but imagine that I am navigated to the main Events screen after a successful login. Then, I am opening the event details and I am pressing the hardware button multiple times: the application will go one step back to the list with events, but after that it will navigate me back to the authentication screen.

WTF? Am I logged out?

Of course that I am not. And this is the normal behaviour — react navigation is checking your “history” and loads your previous navigation steps.

Solution:

To avoid this problem I disable the Android’s back button functionality for the specific tab and screen. In my case, this is the Events tab.

React Navigation has a Router function getStateForAction(action, state) that provides the navigation state for a given action.

The first thing is the store the state of the action in a constant:

const defaultGetStateForAction =   AppNavigator.router.getStateForAction;

Now is time to check the state before running the action: if the leaving screen is Events and the NavigationAction is BACK, then we should return null instead of the state of the action. This will block the process.

The normal Android behaviour is when you don’t have a back step, then it closes the application. And this is what will happen when we return null.

To be honest I don’t like it… I prefer to stay on the same screen. In this case: just delete the previous route and pass the actions.

For all other cases, when we want to trigger the normal behaviour — we simply return the state of the action.

Oh yes, and don’t forget to set it only for Android:

if (Platform.OS === ‘android’) { … }

Check out my ExpoSnack here, or
scan the following QR code to run the demo:

Any comments and suggestions are appreciated :)

--

--