[React Native] 화면 전환(focus) 이벤트
Nadan Dev Blog
화면 전환(focus) 이벤트
다른 화면으로 전환되거나, 현재 화면으로 들어올 때 화면 focus 변화를 탐지하기 위해 사용함. 예를 들어, 어떻게 화면으로 돌아올 때 데이터가 갱신되게 할 수 있을까? 이럴 때 사용함
AppState랑은 활용이 확실이 다른데 처음에 좀 헷갈림. AppState는 앱을 종료하거나, 전화가 오는 등 다른 앱으로 잠시 전환되는 상황에 앱 상태를 탐지하기 위해 사용하는 것임
navigation listener, NavigationEvent는 생각보다 작동이 잘 안 됨. withNavigationFocus이 예의 거의 없이 제일 작동 잘 하는 듯.
1) Navigation Listener
navigation에 리스너를 단 후 리스너 제거할 때 return 값이 listener.remove()가 아니라 () ⇒ listener.remove()임
useEffect(() => {
getBlogPosts();
// any time return to the screen
const listener = navigation.addListener('didFocus', () => {
getBlogPosts();
});
// const listener = navigation.addListener('willBlur', () => {
// });
// memory leak 방지하기 위해 컴포넌트를 사용핮 않을 때 제거
// 컴포넌트 사용이 중지될 떄 호출됨
return () => {
listener.remove();
}
}, []);
2) NavigationEvents
이것과 별개로, 에러 메시지가 뜨면 회원가입 페이지에서도 에러 메시지가 뜸. state가 공용이고, 화면이 사라진 게 아니라 안 보이게 된 것이기 때문. 블로그 만들 때도 비슷한 일이 있었는데, 뒷 페이지로 갈 때 새로 데이터를 갱신하게 하는 것이었음. 이 때 활용한 것이 이벤트 리스너
- onWillFocus → 해당 페이지가 호출 됬을 때
- onDidFocus → 해당 페이지가 화면이 띄워졌을 때
- onWillBlur → 화면에서 나가는 버튼이 눌렸을 때
- onDidBlur → 화면에서 사라졌을 떄
유의점
onWillBlur가 안 되는 경우가 있음. onWillFocus 사용하면 됨
예시)
AuthContext.js
const clearErrorMessage = dispatch => () => {
dispatch({ type: 'clear_error_message' })
};
export const { Provider, Context } = createDataContext(
authReducer,
{ signin, signup, signout, clearErrorMessage },
{ token: null, errorMessage: '' }
)
SignInScreen.js
import { NavigationEvents } from 'react-navigation';
const SignInScreen = () => {
const { state, signin, clearErrorMessage } = useContext(AuthContext);
console.log(state.errorMessage);
return (
<View style={styles.container}>
<NavigationEvents
onWillFocus={() => clearErrorMessage()}
// onDidFocus={() => {}}
// onWillBlur={() => {}}
// onDidBlur={() => {}}
/>
...
</View>
);
};
SignUpScreen.js
import { NavigationEvents } from 'react-navigation';
const SignUpScreen = ({ navigation }) => {
const { state, signup, clearErrorMessage } = useContext(AuthContext);
return (
<View style={styles.container}>
<NavigationEvents
onWillFocus={() => clearErrorMessage()}
/>
...
</View>
);
}
3) withNavigationFocus
import { SafeAreaView, withNavigationFocus } from 'react-navigation';
...
const TrackCreateScreen = ({ isFocused }) => {
const { addLocation } = useContext(LocationContext);
const [err] = useLocation(isFocused, (location) => addLocation(location))
return (
<SafeAreaView>
<Text h2>TrackCreateScreen</Text>
<Map />
{err ? <Text>Please enable loaction services</Text> : null}
</SafeAreaView>
);
};
export default withNavigationFocus(TrackCreateScreen)
참고) BackHandler Listener
BackHandler.addEventListener('hardwareBackPress',() => {
return true;
});