简体   繁体   中英

React Navigation weird back button behavior in nested navigators

I'm using React Navigation in my app and I have a Tab Navigator nested in a Stack Navigator. Sometimes in the app, the navigation stack is:

Screen A => Tab Navigator => Screen B.

So when users are in Screen B and press the back button it triggers first the back action in the Tab Navigator and only if there's no goBack action available in the Tab Navigator that it triggers the goBack action from Screen B.

So, the user gets an unexpected behavior when he is in Screen B and have navigated between Tabs. The user keeps pressing the back button until the Tab Navigator is back to the first tab and only then, after another press in the back button, it goes from Screen B back to the tabs.

Is there anyway I can archieve the expected behaviour in this case?

Are you correctly handling the back button? on each container top level component you need to handle the back button press, ex:

import * as React from 'react';
import { BackHandler } from 'react-native';

export default MyComponent extends React.Component<any, any> {
  public componentDidMount() {
    BackHandler.addEventListener('hardwareBackPress', this.goBack);
  }

  public componentWillUnmount() {
    BackHandler.removeEventListener('hardwareBackPress', this.goBack);
  }

  private goBack = () => {
    this.props.navigation.goBack();
    return true;
  }
}

By returning true, you stop the cascading of the back button press propagation to the previous containers.

If I understand your setup correctly, I think you want to set backBehavior: 'none' on the TabNavigatorConfig . This will prevent tab navigations from pushing history states.

For example:

const MyTabNav = createBottomTabNavigator({
  ScreenOne: ScreenOne,
  ...
}, {
  backBehavior: 'none', // <-- Here
  initialRouteName: 'ScreenOne',
  tabBarOptions: {
    ...
  }
})

If that doesn't do exactly what you want, you might try playing with the other back behaviors. Two new behaviors were just added in version 3.2.0 (see https://github.com/react-navigation/rfcs/blob/master/text/0008-back-behaviour-for-tabs.md ).

You can handle it using BackHandler event in TabNavigator page.

componentDidMount() {
    if ("android" === Platform.OS) {
      BackHandler.addEventListener("hardwareBackPress", this.handleBackPress);
    }
  }

  componentWillUnmount() {
    if ("android" === Platform.OS) {
      BackHandler.removeEventListener(
        "hardwareBackPress",
        this.handleBackPress
      );
    }
  }
  handleBackPress = () => {
    if (this.props.navigation.isFocused()) {
      this.navigateBack();
    } else {      
      this.props.navigation.goBack(null);
    }
    return true;
  };

When hardware back button is pressed in screen B, backhandler method in Tab will get called and the flow will works properly.

But I have an issue in another scenario.

I have following work flow.

Tab Navigator A -> Tab Navigator B -> Screen

When back button is pressed from screen, the issue still persist.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM