게시: 2021년 2월 9일
지인의 스타트업 애플리케이션을 React Native로 제작해주다가 특정 화면에서만 바텀 탭 바가 사라지게 해야 하는 상황이 왔다. 공식 문서를 뒤져봐도 비슷한 코드는 있어도 내가 원하는 코드는 없고 여러 사이트들을 뒤지다가 해결 방법을 찾았다. 해당 사이트에서도 버전 차이 때문인지 문제가 생겨서 응용만 하고 디버깅하며 다시 코딩을 했다.
react-native @0.62.2
typescript @4.0.3
@react-navigation/native @5.7.4
@react-navigation/stack @5.9.1
@react-navigation/bottom-tabs @5.9.0
내가 원하는 플로우는 stack navigation들로 bottom tab bar를 구성하고 특정 stack navigation에서 특정 화면으로 넘어갔을 때만 bottom tab bar가 사라지는 것이다.
아래의 코드에서 알 수 있듯이 bottom tab bar의 첫 번째 탭은 HomeTab이고 HomeTab은 스텍 내비게이션이다. 따라서, 특정 버튼을 누르면 다른 페이지가 렌더링 된다. 이때만 바텀 탭 바를 없애고 싶었는 데, 아래와 같이 options에 route라는 콜백을 받을 수 있고, 이 변수를 파라미터로 getVisibility 함수로 넘겨서 처리하면 된다. 더 자세한 사항은 디버깅을 해보면 알 수 있을 것이다.
아래의 getVisibility에서 selectedIndex는 내가 원하는 페이지가 HomeTab을 생성할 때 Stack.Navigator 안에 쌓인 순서이다. 나는 MathProblem이라는 스크린에서만 바텀 탭을 없앨 것이기 때문에 selectedIndex 값을 1로 줬다.
const getVisibility = (route: any, selectedIndex: number) => {
if (!route.state) return true;
let index = route.state.index;
if (index === selectedIndex) {
return false;
}
return true;
};
const HomeTab = () => {
return (
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="MathProblem" component={MathProblem} />
</Stack.Navigator>
);
};
const MainNavigator = () => {
return (
<BottomTab.Navigator tabBarOptions={{ showLabel: true }}>
<BottomTab.Screen
name="홈"
component={HomeTab}
options={({ route }) => ({
tabBarVisible: getVisibility(route, 1),
tabBarLabel: ({ focused }) => (
<BottomLabel
style={
focused
? { color: "#FF5050" }
: { color: "gray" }
}
>
홈
</BottomLabel>
),
tabBarIcon: ({ focused }) => (
<BottomImage
source={
focused
? require("~/Assets/Images/Tabs/ic_home.png")
: require("~/Assets/Images/Tabs/ic_home_outline.png")
}
style={
focused
? { tintColor: "#FF5050", marginTop: 5 }
: { tintColor: "gray" }
}
/>
),
})}
/>
<BottomTab.Screen
name="바텀1"
component={MyCourseTab}
options={{
tabBarLabel: ({ focused }) => (
<BottomLabel
style={
focused
? { color: "#FF5050" }
: { color: "gray" }
}
>
바텀1
</BottomLabel>
),
tabBarIcon: ({ focused }) => (
<BottomImage
source={
focused
? require("~/Assets/Images/Tabs/ic_class.png")
: require("~/Assets/Images/Tabs/ic_class_outline.png")
}
style={
focused
? { tintColor: "#FF5050", marginTop: 5 }
: { tintColor: "gray" }
}
/>
),
}}
/>
<BottomTab.Screen
name="바텀2"
component={SelfStudyTab}
options={{
tabBarLabel: ({ focused }) => (
<BottomLabel
style={
focused
? { color: "#FF5050" }
: { color: "gray" }
}
>
바텀2
</BottomLabel>
),
tabBarIcon: ({ focused }) => (
<BottomImage
source={
focused
? require("~/Assets/Images/Tabs/ic_study.png")
: require("~/Assets/Images/Tabs/ic_study_outline.png")
}
style={
focused
? { tintColor: "#FF5050", marginTop: 5 }
: { tintColor: "gray" }
}
/>
),
}}
/>
<BottomTab.Screen
name="바텀3"
component={AnalysisTab}
options={{
tabBarLabel: ({ focused }) => (
<BottomLabel
style={
focused
? { color: "#FF5050" }
: { color: "gray" }
}
>
바텀3
</BottomLabel>
),
tabBarIcon: ({ focused }) => (
<BottomImage
source={
focused
? require("~/Assets/Images/Tabs/ic_analysis.png")
: require("~/Assets/Images/Tabs/ic_analysis_outline.png")
}
style={
focused
? { tintColor: "#FF5050", marginTop: 5 }
: { tintColor: "gray" }
}
/>
),
}}
/>
<BottomTab.Screen
name="계정"
component={MyPageTab}
options={{
tabBarLabel: ({ focused }) => (
<BottomLabel
style={
focused
? { color: "#FF5050" }
: { color: "gray" }
}
>
계정
</BottomLabel>
),
tabBarIcon: ({ focused }) => (
<BottomImage
source={
focused
? require("~/Assets/Images/Tabs/ic_account.png")
: require("~/Assets/Images/Tabs/ic_account_outline.png")
}
style={
focused
? { tintColor: "#FF5050", marginTop: 5 }
: { tintColor: "gray" }
}
/>
),
}}
/>
</BottomTab.Navigator>
);
};
export default () => {
return (
<NavigationContainer>
<MainNavigator />
</NavigationContainer>
);
};