[React Native] TabNavigation이 상위인 중첩 네비게이션 구현 (+특정 화면에서 Tab 숨기기)

RuLu·2024년 12월 8일

React-Native

목록 보기
4/13
post-thumbnail

애플리케이션이 일부분에서는 Tab이 보이고 일부분에서는 보이면 안되는 구조를 가질 때 보통은 Stack상위 네비게이션을 만들고 하위에 Tab Navigation을 위치하는 방식으로 구현한다.

하지만 구조를 전체적으로 변경하기 어려운 경우 Tab하위에 Stack이 위치해야할 수도 있을 것이다.

이 Stack Navigation의 몇몇 페이지에서는 Tab이 보이면 안될 수 도 있을 것이다.

상위 네비게이션 (TabNavigation)


const Tab = createBottomTabNavigator<RouteList>(); //전체 경로 타입

function App(): React.JSX.Element {
  return (
    <SafeAreaView style={{flex: 1}}>
      <NavigationContainer>
        <Tab.Navigaton>
		      //하위 네비게이션 연결
          <Tab.Screen
            name="StackNav" 
            component={StackNav}
            options={{
              tabBarIcon: () => <SvgIcon name="Diary" />,
            }}
          />
          ...
        </Tab.Navigator>
      </NavigationContainer>
    </SafeAreaView>
  );
}

export default App;

하위 네비게이션 (StackNavigation)


const Stack = createStackNavigator<RouteList>();

export default (props: DiaryNavigationRouteProps) => {
  const {navigation, route} = props;

  return (
    <Stack.Navigator
      initialRouteName="Diary"
      screenOptions={{headerShown: false, gestureEnabled: true}}>
      <Stack.Screen name="Diary" component={DiaryPage} />
      <Stack.Screen name="WriteDiary" component={DiaryWritePage} />
    </Stack.Navigator>
  );
};

useLayoutEffect를 이용해 특정 페이지에서 Tab 숨기기

StackNav의 안에 useLayoutEffect를 걸어준다.

useLayoutEffect(() => {
    //지금 보고 있는 페이지 이름 가져오기
    const routeName = getFocusedRouteNameFromRoute(route);

    if (routeName !== 'Diary') {
    // 다이어리가 아니면 탭 없애기
      navigation.setOptions({tabBarStyle: {display: 'none'}});
    } else {
    // 다이어리라면 다시 탭 부활
      navigation.setOptions({
        tabBarStyle: {
          height: 52,
          borderTopWidth: 1,
          borderTopColor: theme.color.gray100,
        },
      });
    }
  }, [navigation, route]);

useLayoutEffect를 이용하지 않고 특정 페이지에서 Tab 숨기기

하위 네비게이션은 아래처럼 useLayoutEffect를 작성하지 않는다.

const Stack = createStackNavigator<RouteList>();

export default () => {

  return (
    <Stack.Navigator
      initialRouteName="Diary"
      screenOptions={{headerShown: false, gestureEnabled: true}}>
      <Stack.Screen name="Diary" component={DiaryPage} />
      <Stack.Screen name="WriteDiary" component={DiaryWritePage} />
    </Stack.Navigator>
  );
};

상위 네비게이션에서 StackNav와 연결한 Tab.Screen에 관해 tabBarStyle에 관한 코드를 추가한다.

//App.ts의 Diary에 tabBarStyle 코드 추가
const Tab = createBottomTabNavigator<RouteList>();

function App(): React.JSX.Element {

  return (
    <SafeAreaView style={{flex: 1}}>
      <NavigationContainer>
        <Tab.Navigator
          backBehavior="none"
          screenOptions={{
            headerShown: false,
            tabBarStyle: {
              height: 52,
              borderTopWidth: 1,
              borderTopColor: theme.color.gray100,
            },
          }}>
          <Tab.Screen
            name="StackNav"
            component={StackNav}
            options={({route}) => ({
              tabBarIcon: () => <SvgIcon name="Diary" />,
              tabBarStyle: (route => {
              //여기 부분
                const routeName = getFocusedRouteNameFromRoute(route) ?? '';

                if (routeName !== 'Diary') { //다이어리 페이지가 아니라면
                  return {display: 'none'};
                }
              })(route),
            })}
          />
          ...
        </Tab.Navigator>
      </NavigationContainer>
    </SafeAreaView>
  );
}

export default App;
profile
프론트엔드 개발자 루루

0개의 댓글