React Native/Android

[React Native / Android] 안드로이드 뒤로가기, BackHandler

Juzero 2022. 1. 9. 17:40

안녕하세요.

 

이번 포스팅에서는 안드로이드 뒤로가기 버튼에 대한 이벤트 핸들러를 다뤄보겠습니다.

 

저희 앱은 메인 화면에서 뒤로가기를 누르면 '앱을 종료할까요?' 라는 모달 팝업이 뜨는데요.

이번에 로그인 페이지를 새롭게 추가하니까, 로그인 페이지에서 뒤로가기를 눌러도 앱 종료 모달이 뜨는거 아니겠습니까?

 

메인화면에서 로그인 페이지로 이동했으니 스택이 쌓였고, 로그인페이지에서 뒤로가기를 누르면 다시 이전 스크린으로 가야 정상인데 말이죠.

 

이번 포스팅에서는 안드로이드 뒤로가기 버튼인 Backhandler 이벤트를 사용하는 방법과, 최상단 스크린이 아닌 곳에서는 뒤로가기가 되도록 하는 법을 알아보겠습니다. 

 


1. BackHandler 사용법

 

아래 코드를 import 합니다.

import {BackHandler} from 'react-native';

 

그리고 아래 코드를 통해 뒤로가기를 감지하고, 원하는 동작을 실행할 수 있습니다. 

 

    useEffect(() => {
        // android backhandler
        const backAction = () => {
            //여기에 원하는 동작/함수를 넣습니다.
            console.log("뒤로가기 감지")

            return true;
        };

        const backHandler = BackHandler.addEventListener(
            "hardwareBackPress",
            backAction
        );

        return () => backHandler.remove()

    }, [])

 

정말 간단하죠?

 

 


2. 최상단 스택이 아닌 스크린에서는 뒤로가도록 하기

 

위에서 설명드린 코드를 스택의 최상단 스크린에 넣더라도 다른 스크린에서도 똑같이 동작합니다;;

예를 들면, 아래가 바로보카의 스택 네비게이터 구조인데요. 제 경우에는 RootIndex 스크린에서 백핸들러를 추가하고 console.log를 띄우도록 했다면, LogIn 스크린에서 뒤로가기를 눌러도 뒤로가지 않고 console.log를 띄웁니다. 

 

 

 

앱 구조 때문인지 원래 그런건지는 모르겠지만, 어쩄든 이 문제를 해결해야 했죠. 

(혹시 App.js 파일에서 백핸들러를 호출해주어야하나?)

 

저는 현재 스크린의 이름을 받아와서, 최상단 스크린(RootIndex)이면 별도로 설정한 함수가 작동하고, 그 이외에 스크린이면 뒤로가기가 실행되도록 해결했습니다. 

 

 

BackHandler가 작동되는 스크린 파일에서 아래 코드를 import합니다.

 

import {useRoute} from '@react-navigation/native';

 

그리고 route 상수를 선언해서 넣어줍니다. 

 

const route = useRoute();

 

그리고 route.name으로 현재 파일의 스크린 이름을 받아와요.

route.name이 최상단 스크린이면 제가 원하는 동작을 실행하고, 다른 스크린이면 navigation.pop()으로 뒤로가기를 해줍니다.

    useEffect(() => {
        // android backhandler
        const backAction = () => {
            if(route.name === 'RootIndex'){
                console.log("Here is main screen")
            } else {
                navigation.pop()
            }

            return true;
        };

        const backHandler = BackHandler.addEventListener(
            "hardwareBackPress",
            backAction
        );

        return () => backHandler.remove()

    }, [])

 

 

끝!