
애플리케이션이 일부분에서는 Tab이 보이고 일부분에서는 보이면 안되는 구조를 가질 때 보통은 Stack상위 네비게이션을 만들고 하위에 Tab Navigation을 위치하는 방식으로 구현한다.
하지만 구조를 전체적으로 변경하기 어려운 경우 Tab하위에 Stack이 위치해야할 수도 있을 것이다.
이 Stack Navigation의 몇몇 페이지에서는 Tab이 보이면 안될 수 도 있을 것이다.
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;
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>
);
};
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를 작성하지 않는다.
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;