설정 중에 특정 데이터를 쿼리로 보내고 + firebase로 메시지를 보내는 이벤트가 있었다. 원래는 뒤로가기 버튼에 이 이벤트 핸들러를 넣어서 뒤로 가기가 한참 뒤에야 뒤로 가졌다. 그 부분은 해결을 했지만, Swipe로 뒤로 가기를 매우 급하게(?) 할 경우 사용자가 저장한 설정이 제대로 서버로 전달을 주지 못하고 navigation이 이뤄지는 바람에 제대로 설정 정보를 불러오지 못하는 이슈가 있었다.
첫 번째로 생각난 것이 "일단 Loading UI를 사용자에게 제공해주자"였다. 페이지를 개발하다 보면 다양한 상황에서 서버에서 데이터를 fetch하여 사용자에게 정보를 제공한다. fetch하는 시간동안 나은 UX를 제공하기 위한 방법으로 Loading UI를 사용자에게 제공한다.
두 번째로 생각난 것이 Loading 중에 뒤로가기를 막아서 데이터가 서버로 보내지기 전에 Swipe로 뒤로 가는 것은 막되, 서버로 전달이 끝나면 다시 Swipe가 되도록 해야했다.
React Navigation 공식 문서에서 제공하는 뒤로 가기 방지의 예시를 참조하여 navigation에 이벤트를 붙여보았다. beforeRemove
이벤트를 붙이면, 현재 stack이 삭제되고 다른 stack으로 이동하는 순간 해당 이벤트가 트리거된다.
나의 경우 stack에서 tab으로 이동을 하는 거 때문이었는지 몰라도 (아직도 잘 확인이 안된다😭) 자꾸만 에러를 뿜었다.
The screen was removed natively but didn't get removed from JS state.
해석하자면 현재 화면은 iOS에서 사라졌지만 JS 상태에서는 삭제가 되지 않았다고 한다. (이해하려면 더 공부가 필요하지만) 공식 문서에서도 사실 비슷한 이야기가 나온다.
The event is only triggered whenever a screen is being removed due to a navigation state change.
이런 에러로 인해 위에서 말했던 beforeRemove
이벤트를 navigation에 붙여서 사용할 수 없었다.
위 에러 사진에서 친절하게 대안을 제시해준다. gestureEnabled
를 false로 주면 된다고 한다.
stack-navigator의 옵션으로 false로 설정할 경우 (기본값은 true임) swipe와 같은 gesture가 막히게 된다. 근데 이건, stack 자체의 swipe를 막은거라 loading 중에만 막고 loading 아닌 경우에는 열어 놓는다는 원래 아이디어와 맞지 않았기 때문에 사실상 시도하지 않았다.
useEffect를 이용하여 의존성 배열에는 loading의 state를 넣어 주었다. 그리고 navigation.setOptions()
으로 gestureEnabled
값을 변경해 주는 함수를 실행시켰더니 원하던 아이디어대로 구현이 되었다.
useEffect(() => {
navigation.setOptions({ gestureEnabled: !isLoading })
}, [isLoading])
isLoading이 true일때 gestureEnabled가 false로 setter함수가 옵션을 보내주고, 반대의 경우 true로 보내주기 때문에 loading state에 따라서 해당 옵션값이 잘 변경되었다.
React Native는 iOS와 안드로이드에 맞게 상태를 관리하고 옵션 등을 잘 설정해 주어야 한다는 것을 다시 한번 깨닳았다. 구글링을 아무리해도 해외 개발자 형님들도 이 부분에 대해 명확하게 설명하고 있지 않은 것 같았다. 끝내 setOption
이라는 navigtaiton
이 제공하는 프로퍼티를 이용하여 이 이슈를 해결할 수 있었다.