Tab Navigation은 화면 위에 쌓는 것이 아니라 선택된 버튼에 해당하는 화면으로 전환된다는 특징이 있다.
공식문서 : https://reactnavigation.org/docs/bottom-tab-navigator/
$ /npm install @react-navigation/bottom-tabs
생성된 Tab Navigation에는 Navigator 컴포넌트와 screen 컴포넌트를 이용해서 내비게이션과 화면을 구성한다.
createBottomTabNavigator를 이용해서 생성된 탭에는 Navigator과 Screen 컴포넌트가 있다.
// Tab Navigation 생성
const Tab = createBottomTabNavigator()
<Tab.Navigator>
<Tab.Screen>
</Tab.Screen>
</Tab.Navigator>
import React from 'react';
import styled from 'styled-components/native';
const Container = styled.View`
flex: 1;
justify-content: center;
align-items: center;
`;
const StyledText = styled.Text`
font-size: 30px;
`;
export const Mail = () => {
return (
<Container>
<StyledText>Mail</StyledText>
</Container>
);
};
export const Profile = () => {
return (
<Container>
<StyledText>Profile</StyledText>
</Container>
);
};
export const Settings = () => {
return (
<Container>
<StyledText>Setting</StyledText>
</Container>
);
};
//index.js
import Home from './Home';
import List from './List';
import Chat from './Chat';
import { Mail, Profile, Settings } from './TabScreens';
export { List, Chat, Home, Mail, Profile, Settings };
navigation과 route가 props로 전달된다. import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Mail, Profile, Settings } from '../screens';
const Tab = createBottomTabNavigator();
const TabNav = () => {
return (
<Tab.Navigator>
<Tab.Screen name='Mail' component={Mail} />
<Tab.Screen name='Profile' component={Profile} />
<Tab.Screen name='Settings' component={Settings} />
</Tab.Navigator>
);
};
export default TabNav;
import { NavigationContainer } from '@react-navigation/native';
import React from 'react';
import TabNav from './Tab';
const Navigation = () => {
return (
<NavigationContainer>
<TabNav />
</NavigationContainer>
);
};
export default Navigation;
import React from 'react';
import Navigation from './navigations';
export default function App() {
return (
<Navigation />
);
}
잘 보인다.

Tab navigation에 첫번째로 보이는 화면은 Screen 컴포넌트의 순서이다. Tav 내비게이션을 사용할 떄 스크린 컴포넌트의 순서는 탭바의 버튼의 순서이기도 한다.
const TabNav = () => {
return (
<Tab.Navigator>
<Tab.Screen name='Profile' component={Profile} />
<Tab.Screen name='Mail' component={Mail} />
<Tab.Screen name='Settings' component={Settings} />
</Tab.Navigator>
);
};
순서에 따라 달라지는 것을 볼 수 있다.

initialRouteName를 사용하면 버튼의 순서는 유지한 상태에서 첫번째 보이는 화면의 순서를 변경

const TabNav = () => {
return (
<Tab.Navigator initialRouteName='Mail'>
<Tab.Screen name='Profile' component={Profile} />
<Tab.Screen name='Settings' component={Settings} />
<Tab.Screen name='Mail' component={Mail} />
</Tab.Navigator>
);
};
tabBarIcon에 들어오는 props를 확인해보면
<Tab.Screen
name='Mail'
component={Mail}
options={{
tabBarIcon: (props) => {
console.log(props);
return null;
},
}}
/>
이런식으로 들어온다.
{"color": "#8E8E8F", "focused": false, "size": 25}
focused는 현재의 버튼이 선택되었는지 않되었는지 알려주는 값
import { MaterialIcons } from '@expo/vector-icons';
(...)
<Tab.Screen
name='Mail'
component={Mail}
options={{
tabBarIcon: (props) => {
return <MaterialIcons name='mail' size={props.size} color={props.color} />;
},
}}
/>
아이콘 변경 함수를 만들어서 다른 아이콘도 적용
import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Mail, Profile, Settings } from '../screens';
import { MaterialIcons } from '@expo/vector-icons';
//아이콘 변경 함수
//파라미터로 name, size, color를 받고 아이콘을 이용해 컴포넌트를 반환
const TabIcon = ({ name, size, color }) => {
return <MaterialIcons name={name} size={size} color={color} />;
};
const Tab = createBottomTabNavigator();
const TabNav = () => {
return (
<Tab.Navigator initialRouteName='Mail'>
<Tab.Screen
name='Profile'
component={Profile}
options={{
tabBarIcon: (props) => {
return TabIcon({ ...props, name: 'person' });
},
}}
/>
<Tab.Screen
name='Settings'
component={Settings}
options={{
tabBarIcon: (props) => {
return TabIcon({ ...props, name: 'settings' });
},
}}
/>
<Tab.Screen
name='Mail'
component={Mail}
options={{
tabBarIcon: (props) => {
return TabIcon({ ...props, name: 'mail' });
},
}}
/>
</Tab.Navigator>
);
};
export default TabNav;
잘 변경된다.

<Tab.Screen
name='Mail'
component={Mail}
options={{
tabBarIcon: (props) => {
return TabIcon({ ...props, name: 'mail' });
},
tabBarLabel: 'Inbox',
}}
/>

tabBarLabel: ''이렇게 빈배열을 주기 되면 아래와 같이 빈 string이 렌더링 된다.

Navigator 컴포넌트의 tabBarOptions에서 showLabel를 설정하면 전체에서 라벨의 렌더링를 설정할 수 있다.
<Tab.Navigator initialRouteName='Mail' tabBarOptions={{ showLabel: false }}>

위와 같은 경고문이 나온다. 해석해보자면
tabBarOptions는 없어졌으니screenOptions으로 마이그레이션하라는 뜻이다. 공식문서를 찾아보니
공식문서 : https://reactnavigation.org/docs/upgrading-from-5.x/#the-tabbarvisible-option-is-no-longer-present
읽어보면 그 전에 tabBarOptions 안에 썼던 프로퍼티들 앞에 tabBar만 붙이면 사용가능하다.
그래서 screenOptions를 활용해서 아래와 같이 사용해 주었더니 잘 작동한다.
<Tab.Navigator
initialRouteName='Mail'
//`tabBarLabelPosition: 'beside-icon'`설정시
screenOptions={{ tabBarShowLabel: true, tabBarLabelPosition: 'beside-icon' }}
>

참고로, tabBarLabelPosition: 'below-icon'로 설정시 라벨은 icon의 아래로 향한다.

<Tab.Navigator
initialRouteName='Mail'
screenOptions={{
tabBarShowLabel: true,
tabBarLabelPosition: 'below-icon',
tabBarStyle: {
backgroundColor: 'gray',
borderTopColor: 'red',
borderTopWidth: 3,
},
}}
>

tabBarActiveTintColor: '#ffffff',
tabBarInactiveTintColor: '#333333',

<Tab.Screen
name='Profile'
component={Profile}
options={{
tabBarIcon: (props) => {
return TabIcon({ ...props, name: props.focused ? 'person' : 'person-outline' });
},
}}
/>
선택 전

선택 후
