React-native-navigation: Backpress closes app instead of `pop` from stack

Created on 29 Jun 2018  ·  18Comments  ·  Source: wix/react-native-navigation

I am trying to migrate from version 1.x to 2.x. I got an issue where the 'back' button on the bottom of your Android phone does not pop to the previous screen, but closes the app.

This is how my setRoot looks like:

      Navigation.setRoot({
        root: {
          sideMenu: {
            left: {
              component: {
                name: constants.DrawMenu
              }
            },
            center: {
              stack: {
                options: {

                },

                children: [
                  {
                    component: {
                      name: startScreen
                    }
                  }
                ]
              }
            }
          }
        }
      })

This is how I push from my startScreen to my next screen:

    this.NavigationService.Navigation.push(this.props.componentId, {
      component: {
        name: routes.TimelineContent,
        passProps: {
          index,
          items: this.state.timeline
        }
      }
    }) 

Can anybody give me a hint why this happens? When I am at my TimelineContent and I press the back button of my Android phone (at the bottom, the left triangle), I won't go to my startScreen, but the app will close.

Thanks in advance!

Bob

more info needed v2 🏚 stale

Most helpful comment

Hey, I'm experiencing the same problem.

It seem that when I use 'sideMenu' as the root element, the back button will quit the app (even after pushing another screen on to a center stack). When I removed the sideMenu and had just a stack as root, the back button pops the topmost screen.

All 18 comments

Hey @bobmulder
On which platform does this happen? Can you please include a failing Detox e2e test?

Hi @guyca, this happens on Android. How do I add a failing Detox test? Using playground?

Yes. npm install in the root directory, then run the app located in ./playground/android from Android Studio.
You can run the e2e suite using npm run test-e2e-android

I've already tested the Android version of the playground app op my phone. The issue doesn't pop up, so I guess it's about my setRoot structure.

Hey, I'm experiencing the same problem.

It seem that when I use 'sideMenu' as the root element, the back button will quit the app (even after pushing another screen on to a center stack). When I removed the sideMenu and had just a stack as root, the back button pops the topmost screen.

I'm using react native navigation 2.0.2411 and i'm having the same issue.
const sideMenu = { left: { component: {} }, center: { stack: {} }, right: { component: {} } }
if I use this sideMenu layout, the hardware back press exists the app for some reason instead of popping the current screen.
const stack = { children: [ { component: {} }, { component: {} } ], options: {} }
However, with this stack layout, back press works just fine.

Also happens with my structure:

      Navigation.setRoot({
        root: {
          sideMenu: {
            left: {
              component: {
                id: 'DashboardDrawer',
                name: 'operatorreact.DashboardDrawer',
              },
            },
            center: {
              stack: {
                id: DASHBOARD_ROUTE,
                children: [
                  {
                    component: {
                      name: 'operatorreact.Dashboard',
                    },
                  }
                ],
              },
            },
          }
        },
      });

After many pushes, if I hit hardware back button the app always exit.

@guyca any update on this ?

Having the same issue here

Just an info: if you guys really need to ship, you can always implement by yourselves with BackHandler inside the components:

https://facebook.github.io/react-native/docs/backhandler

For example:

  constructor(props) {
    super(props);
    Navigation.events().bindComponent(this);
  }

  componentDidAppear() {
    BackHandler.addEventListener('hardwareBackPress', this.onHardwareBackPress);
  }

  componentDidDisappear() {
    BackHandler.removeEventListener('hardwareBackPress', this.onHardwareBackPress);
  }

  onHardwareBackPress = () => {
    Navigation.pop(this.props.componentId);
    return true;
  }

Or a more complex solution with redux+saga, handle this within your side-effects.

Same issue about exiting the app when the screen is pushed from constants.DrawMenu in your example.

@gabrielhpugliese
Your solution works well. Hope the team will fix it soon.

@gabrielhpugliese
Thank you for the 'workaround' , but i ended up adding this to almost every screen ;) .
I am using redux saga can you please provide an example of how to handle this with saga (eventChannel for ex)
Thanks

RNN v: 2.0.2425
RN v: 0.56.0

Unfortunately I don't have it done, but the idea is to save the current
componentId into the state and call the pop when you have the hardware
press (use yield select)

On Sun, Jul 29, 2018, 5:34 PM BillelNorm notifications@github.com wrote:

@gabrielhpugliese https://github.com/gabrielhpugliese
Thank you for the 'workaround' , but i ended up adding this to almost
every screen ;) .
I am using redux saga can you please provide an example of how to handle
this with saga (eventChannel for ex)
Thanks


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/wix/react-native-navigation/issues/3466#issuecomment-408685690,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABMd0gSQbxKbem8vazl2Vml9P8SUnNiLks5uLdYUgaJpZM4U9cKM
.

I also ended up overriding the back button.

I did it in the HOC I used to provide the redux store:

  function provideStore(ConnectedComponent, store) {
    return class extends React.Component {
      static get options() {
        try {
          return ConnectedComponent.options;
        } catch (e) {
          return {};
        }
      }

      /*
        The following methods is to work around a bug in RNN v2 where the physical back button on
        Android always closes the app, instead of poping a screen from the current stack (when
        using sidemenu).
       */
      componentDidMount() {
        BackHandler.addEventListener('hardwareBackPress', this.handleBackPress);
      }

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

      handleBackPress = async () => {
        try {
          await Navigation.pop(this.props.componentId);
          return true;
        } catch (e) {
          BackHandler.exitApp();
          return false;
        }
      };

      render() {
        return (
          <Provider store={store}>
            <ConnectedComponent {...this.props} />
          </Provider>
        );
      }
    };

@geirr Thank you , it works

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you believe the issue is still relevant, please test on the latest version and report back. Thank you for your contributions.

The issue has been closed for inactivity.

Was this page helpful?
0 / 5 - 0 ratings