https://khw063011.tistory.com/44
하단바 각각에 navigation 을 설정해두었는데
이번에 하단바에서 좀 수정하고싶은 오류가 생겨서 공부를 하다가
네비게이션 상태에 대해 좀 더 공부할 게 생겨서 포스팅을 한당
1. 문제상황
지금 나는 게시판을 작성하는 글 작성 페이지와
작성된 글들을 볼 수 있는 커뮤니티 페이지로 나눠서 관리하고 있었는데
서버와 잘 연결하여 글을 성공적으로 등록하면
바로 커뮤니티 글들이 담긴 페이지로 자동으로 넘어가게끔 했다.
그런데 문제는... 하단바랑 동기화가 잘 되지 않는 것을 확인할 수 있었다.
내가 직접 터치하여 고를 때는 페이지가 잘 넘어갔었는데
자동으로 커뮤니티 페이지로 넘어가야 할 때에는 여전히 글 작성 페이지에서 screen 만 커뮤니티 페이지인것을 확인할 수 있었다.
나는 이게 싫어서 하단바와 동기화가 잘 되었음 좋겠어서 내 코드의 상태를 다시 확인해보았다.
분명 selected 상태가 업데이트가 잘 되는 것은 맞는데 네비게이션 상태와 bottom bar 상태가 동기화가 잘 되지 않아
화면 전환이 되어도 이전의 탭이 활성화되는 것처럼 표시되는 것 같다.
🤔 흠 어떻게 수정할 수 있을까?
기존 코드
import { TouchableOpacity, View, Text, StyleSheet } from 'react-native';
import { useNavigation } from '@react-navigation/native';
const BottomBar = () => {
const [selectedTab, setSelectedTab] = useState('홈');
const navigation = useNavigation();
const tabs = [
{ name: '홈', icon: 'home', screen: '홈' },
{ name: '커뮤니티', icon: 'team', screen: '커뮤니티' },
];
return (
<View style={styles.container}>
{tabs.map((tab) => (
<TouchableOpacity
key={tab.name}
onPress={() => {
setSelectedTab(tab.name);
navigation.navigate(tab.screen);
}}
style={styles.tabItem}
>
</TouchableOpacity>
</View>
);
};
기존 코드이다. 화면을 전환하는데에는 문제가 없지만... 자꾸 bottom bar 와 화면이 동기화가 안되는 부분이 있어서 개선이 필요했다.
📌 useNavigationState 사용하기
일단 기존의 useNavigation 은!
- 네비게이션 객체 자체에 접근
- 주로 화면 간 이동(navigatie, push, goBack) 등을 수행
- 네비게이션 작업을 수행하는 데 필요한 메서드 제공
//예시코드
const navigation = useNavigation(); navigation.navigate('Home');
useNavigationState 란?
- 네비게이션의 전체 상태에 접근할 수 있게 함
- 현재 라우트, 라우트 스택, 파라미터 등 네비게이션의 모든 상태 정보 가져옴
- 상태 변화 감지하고 반응
//예시코드
const currentRouteName = useNavigationState(state => state.routes[state.index].name);
🤔 useNavigation 과 useNavigationState 의 차이점이 뭘까??
useNavigation 은 네비게이션의 작업정보를 수행하고
useNavigationState 는 네비게이션의 상태정보를 읽는데 사용이 된다.
따라서 useNavigation은 네비게이션 객체 자체는 변경되지 않기 때문에 렌더링되지 않고
UseNavigationState는 네비게이션 상태가 변경될 때마다 컴포넌트를 다시 렌더링하게 된다.
따라서 네비게이션 작업만 수행하여 상태변화로 인한 추가 렌더링이 필요하지 않을 때는 useNavigation 만사용해도 무방하고
필요한 상태를 구독하여 필요한 상태만 리렌더링이 필요할 때에는 useNavigationState를 하여 추가적인 리렌더링이 이루어질 수 있게 한다.
정리!!
useNavigation
-화면 간 이동같은 네비게이션 작업 수행
-객체 자체는 변경되지 않아 리렌더링 이루어지지 않음
useNavigationState
-네비게이션 상태의 특정부분(ex. 현재 라우트이름) 을 구독하고 변화에 반응
-상태가 변경할 때마다 컴포넌트 다시 렌더링
=> 따라서 useNavigationState 로 현재 상태를 파악하고 useNavigation 으로 필요한 네비게이션 작업을 수행한다.
이번엔 내 코드를 개선해보자!
(1) useNavigation 임포트
import { useNavigation, useNavigationState } from '@react-navigation/native';
(2) useNavigationState 를 사용하여 현재 네비게이션 상태에 접근하기
- 콜백 함수를 인자로 받아 그 함수의 반환값을 제공함
- state => 로 usenavigationState 에 콜백함수 전달
- 여기서 state의 매개변수는 전체 네비게이션의 상태 객체이다.
- state ?. routes : 현재 네비게이터에 있는 모든 화면의 배열
- [state.index] : 현재 활성화된 객체에 접근함
- 네비게이션 상태 가져옴-> 현재 활성화된 라우트의 인덱스 찾기-> 인덱스를 사용하여 활성 라우트 객체에 접근-> 해당 라우트 객체에서 이름 추출
const BottomBar = () => {
const [selectedTab, setSelectedTab] = useState('홈');
const navigation = useNavigation();
const currentRouteName = useNavigationState(state => state?.routes[state.index]?.name);
- 현재 라우트 이름이 변경될 때마다 선택된 탭 업데이트
- 의존성배열: currentRouteName 으로 줘서 currentRouteName(현재 라우트이름) 이 변경될 때마다 효과 실행되게 함
- 이 코드를 통해 사용자가 다른 화면으로 이동할 때마다 bottombar의 선택된 탭을 자동으로 업데이트하여 bottombar 과 선택된 탭이 항상 일치하도록 보장함
useEffect(() => {
if (currentRouteName) {
const currentTab = tabs.find(tab => tab.screen === currentRouteName);
if (currentTab) {
setSelectedTab(currentTab.name);
}
}
}, [currentRouteName]);
reference
'모바일 > React Native' 카테고리의 다른 글
[RN] 카카오 로그인 하기 구현하기 (6) | 2024.08.30 |
---|---|
[RN] 🚧 asyncstorage 알아보기 (0) | 2024.08.26 |
[RN] axios (0) | 2024.08.09 |
[RN] route params 알아보기 (0) | 2024.08.07 |
AxiosError:Network Error 수정하기 (0) | 2024.07.25 |