szskdgi
szskdgi

Reputation: 305

How to handle back button behavior in bottom tabs in React Native?

I have a @react-navigation/bottom-tabs navigator when my app opens whose contents are like:

    <Tab.Navigator
        tabBarOptions={{
            activeTintColor: '#77dd77',
            inactiveTintColor: 'gray',
        }}
        tabBar={props => <MyTabBar {...props} />}
        backBehavior={"history"}
        >
        <Tab.Screen
            name="Home"
            component={Home}
            options={{ title: 'Home' }}
        />
        <Tab.Screen
            name="Orders"
            component={Orders}
            options={{ title: 'Orders' }}
        />
        <Tab.Screen
            name="Profile"
            component={Profile}
            options={{ title: 'Profile' }}
        />
    </Tab.Navigator>

I have a BackHandler in my code that makes the app exit when back button is pressed from the home page. Everything is fine and I have checked that the backhandler gets called when back button is pressed.

But when I switch to any other tab and then return to the homepage and press back to exit the app, backhandler stops working and the app shows error "The action 'GO_BACK'was not handled by any navigator. Is there any screen to go back to?"

This is a development-only warning but in the signed version, the app doesn't show any error and doesn't even exit.

How can I address this 'GO_BACK' action?

Upvotes: 10

Views: 11243

Answers (4)

Abhi
Abhi

Reputation: 1177

Simple and Clean solution using Custom hook.

I have created a custom hook to handle back press in all bottom tabs.

// back handler hook
import React from 'react';
import {useEffect} from 'react';
import {BackHandler} from 'react-native';

export const useBackButton = (props, handler) => {
    useEffect(() => {
        props.navigation.addListener('focus', () => {
            BackHandler.addEventListener('hardwareBackPress', handler);
        });
        props.navigation.addListener('blur', () => {
            BackHandler.removeEventListener('hardwareBackPress', handler);
        });
    }, [handler]);
};

Now In home screen I added this

   const onBackPress = () => {
        BackHandler.exitApp();
        return true;
    };
    useBackButton(props, onBackPress);

And In other screens I added following.

   const onBackPress = () => {
        props.navigation.goBack();
        return true;
    };
        useBackButton(props, onBackPress);

Upvotes: 1

YosefBro
YosefBro

Reputation: 654

I was facing a similar issue, just found out the solution.

The problem was that I was trying to handle backHandler from the screen itself, but it just doesn't work like that with tab navigator (and maybe with react-navigation as a whole? I dunno).

Any way, you just need to add a listener for 'focus' (~componentDidMount) and 'blur' (~componentWillUnmount) like this:

        <Tab.Screen name="Home" component={HomeScreen} 
          listeners={{ focus: () => BackHandler.addEventListener('hardwareBackPress',handleBackButton)
                      ,blur: () => BackHandler.removeEventListener('hardwareBackPress',handleBackButton)
          }}
        />

Where:

function handleBackButton  ()  {
  BackHandler.exitApp();
  return true;
}

Now the backHandler function works in this way only in HomeScreen, and as usual in other screens.

Upvotes: 9

Farrukh Atabekov
Farrukh Atabekov

Reputation: 81

React Navigation (version 5) has already handled the native back button on bottom tabs.

I was stuck with this issue for one day and tried so many ways.

I ended up finding out in react-navigation version_5 that they have included it with just one line. https://reactnavigation.org/docs/bottom-tab-navigator/#backbehavior

Add the prop backBehaviour = "initialRoute" to your <Tab.Navigator/> and that will handle all native back button on tabs

 <Tab.Navigator backBehaviour = "initialRoute" >
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen name="Settings" component={SettingsScreen} />
 </Tab.Navigator>

Upvotes: 4

szskdgi
szskdgi

Reputation: 305

I was using backhandler in all my tabs to create a navigation flow I wanted. Turns out this was creating the issue. After removing the backhandlers from the rest tabs, the app runs smoothly now.

I am now trying to experiment more with backBehavior in tab navigator to try to get the flow I want.

Writing my problem here gave me a clearer view of my problem!

Upvotes: 1

Related Questions