Skip to content
This repository has been archived by the owner on Jan 13, 2023. It is now read-only.

Exit route not working on android back button press #357

Open
archansel opened this issue Jun 25, 2020 · 2 comments
Open

Exit route not working on android back button press #357

archansel opened this issue Jun 25, 2020 · 2 comments

Comments

@archansel
Copy link

What's going on?

After upgrading to react navigation 5, back button handle for exit route not working, in fact it's not even registering, so any routes defined in export const exitRoutes: string[] = ["welcome", "demo"] won't exit app, but trigger default bahavior


Expected result

App will exit if currently showing route in exitRoutes


Steps to reproduce

  1. Install fresh ignite bowser
  2. Change the exit routes, add "demo" route
  3. Run app
  4. Navigate to demo screen
  5. Press hardware back

It will go back to welcome screen instead of exiting app


Current workaround

  1. Using device event emiter, this will remove all hardwareBackPress handler from other libs too
import { useEffect, useRef, useState } from "react"
import { BackHandler, DeviceEventEmitter } from "react-native"
import { NavigationContainerRef } from "@react-navigation/native"
import getActiveRouteName from "./get-active-routename"

export function useBackButtonHandler(
  ref: React.RefObject<NavigationContainerRef>,
  canExit: (routeName: string) => boolean,
) {
  const [backPressSubscriptions] = useState(new Set())
  const canExitRef = useRef(canExit)

  useEffect(() => {
    canExitRef.current = canExit
  }, [canExit])

  useEffect(() => {
    // We'll fire this when the back button is pressed on Android.
    const handleBackPress = () => {
      const navigation = ref.current

      if (navigation == null) {
        return false
      }

      // grab the current route
      const routeName = getActiveRouteName(navigation.getRootState())

      // are we allowed to exit?
      if (canExitRef.current(routeName)) {
        // let the system know we've not handled this event
        return false
      }

      // we can't exit, so let's turn this into a back action
      if (navigation.canGoBack()) {
        navigation.goBack()
        return true
      }

      return false
    }

    // Subscribe when we come to life
    DeviceEventEmitter.removeAllListeners("hardwareBackPress")
    DeviceEventEmitter.addListener("hardwareBackPress", () => {
      let invokeDefault = true
      const subscriptions = []

      backPressSubscriptions.forEach(sub => subscriptions.push(sub))

      for (let i = 0; i < subscriptions.reverse().length; i += 1) {
        if (subscriptions[i]()) {
          invokeDefault = false
          break
        }
      }

      if (invokeDefault) {
        BackHandler.exitApp()
      }
    })

    backPressSubscriptions.add(handleBackPress)

    // Unsubscribe when we're done
    return () => {
      DeviceEventEmitter.removeAllListeners("hardwareBackPress")
      backPressSubscriptions.clear()
    }
  }, [ref])
}
  1. Using custom back handler by react navigation 5 https://reactnavigation.org/docs/custom-android-back-button-handling, put this in every screen you want to exit on back press, current issue, it won't register on the first time, so back will still go back to previous screen
export function useExitOnBack(routeName: string) {
  useFocusEffect(
    useCallback(() => {
      const handleBackPress = () => {
        BackHandler.exitApp()
        return true
      }

      BackHandler.addEventListener("hardwareBackPress", handleBackPress)
      return () => BackHandler.removeEventListener("hardwareBackPress", handleBackPress)
    }, [routeName]),
  )
}

ignite doctor results:

System
  platform           darwin                                                                       
  arch               x64                                                                          
  cpu                4 cores      Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz                        
  directory          BSQ Mobile   /Users/Ansel/Desktop/Repositories/Projects/Radyalabs/BSQ Mobile 

JavaScript
  node               12.17.0      /usr/local/bin/node 
  npm                6.14.4       /usr/local/bin/npm  
  yarn               1.22.4       /usr/local/bin/yarn 

Ignite
  ignite-cli           3.5.1                                                                                                        /usr/local/bin/ignite                                          
  ignite src           build                                                                                                        /Users/Ansel/.config/yarn/global/node_modules/ignite-cli/build 
  navigation           react-navigation                                                                                                                                                            
  generators           {"component":"ignite-bowser","model":"ignite-bowser","navigator":"ignite-bowser","screen":"ignite-bowser"}                                                                  
  createdWith          3.5.1                                                                                                                                                                       
  boilerplate          ignite-bowser                                                                                                                                                               
  boilerplateVersion   5.0.3                                                                                                                                                                       

Android
  java               1.8.0_242    /usr/bin/java                    
  android home       -            /Users/Ansel/Library/Android/sdk 

iOS
  xcode              11.5       
  cocoapods          1.8.4        /usr/local/bin/pod 
@StijnCoolen
Copy link

Seems like React navigation V5 does not support useEffect(), see: https://reactnavigation.org/docs/custom-android-back-button-handling/#why-not-use-component-lifecycle-methods

@imfly
Copy link

imfly commented Oct 22, 2021

+1

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants