Created
February 11, 2022 16:06
-
-
Save ChlorUpload/6e9d255d2ca617448c37e52e9fdd1bdd to your computer and use it in GitHub Desktop.
react-navigation extension custom hook that enables a certain route to exit the app when back button is pressed twice.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { NavigationProp, useNavigation } from '@react-navigation/native'; | |
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; | |
import { | |
BackHandler, | |
AppState, | |
AppStateStatus, | |
Platform, | |
ToastAndroid, | |
} from 'react-native'; | |
const TOLERATION_TIME = 2000; | |
export function useDoubleBackExit() { | |
/** | |
* enable conditions | |
*/ | |
const [active, setActive] = useState(false); | |
const [focused, setFocused] = useState(false); | |
/** | |
* app state active | |
*/ | |
const handleAppState = useCallback( | |
(nextAppState: AppStateStatus) => { | |
setActive(nextAppState === 'active'); | |
}, | |
[setActive], | |
); | |
useEffect(() => { | |
setActive(AppState.currentState === 'active'); | |
const subscription = AppState.addEventListener('change', handleAppState); | |
return () => { | |
subscription.remove(); | |
}; | |
}, [handleAppState]); | |
/** | |
* navigation focused | |
*/ | |
const navigation = useNavigation(); | |
const handleFocusNavigation = useCallback(() => { | |
setFocused(true); | |
}, [setFocused]); | |
const handleBlurNavigation = useCallback(() => { | |
setFocused(false); | |
}, [setFocused]); | |
useEffect(() => { | |
setFocused(navigation.isFocused()); | |
navigation.addListener('focus', handleFocusNavigation); | |
navigation.addListener('blur', handleBlurNavigation); | |
return () => { | |
navigation.removeListener('focus', handleFocusNavigation); | |
navigation.removeListener('blur', handleBlurNavigation); | |
}; | |
}, [handleFocusNavigation, handleBlurNavigation]); | |
const enabled = useMemo(() => active && focused, [active, focused]); | |
/** | |
* back handler | |
*/ | |
const backPressed = useRef<number | null>(null); | |
const handleBack = useCallback(() => { | |
const current = Date.now(); | |
if ( | |
backPressed.current !== null && | |
current - backPressed.current < TOLERATION_TIME | |
) { | |
BackHandler.exitApp(); | |
backPressed.current = null; | |
} else { | |
if (Platform.OS === 'android') { | |
ToastAndroid.show('한 번 더 누르시면 종료됩니다.', ToastAndroid.SHORT); | |
} | |
} | |
backPressed.current = current; | |
return true; | |
}, []); | |
/** | |
* back handler registration | |
*/ | |
useEffect(() => { | |
if (enabled) { | |
BackHandler.addEventListener('hardwareBackPress', handleBack); | |
return () => { | |
BackHandler.removeEventListener('hardwareBackPress', handleBack); | |
backPressed.current = null; | |
}; | |
} | |
}, [handleBack, enabled]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment