Custom tab bars let you change how the bottom navigation looks and works in your app. This helps make your app unique and easier to use.
Custom tab bars in React Native
function MyTabBar({ state, descriptors, navigation }) {
return (
<View style={{ flexDirection: 'row' }}>
{state.routes.map((route, index) => {
const isFocused = state.index === index;
const onPress = () => {
const event = navigation.emit({
type: 'tabPress',
target: route.key,
canPreventDefault: true
});
if (!isFocused && !event.defaultPrevented) {
navigation.navigate(route.name);
}
};
return (
<TouchableOpacity
key={route.key}
onPress={onPress}
style={{ flex: 1, padding: 10, backgroundColor: isFocused ? '#ddd' : '#fff' }}
>
<Text>{route.name}</Text>
</TouchableOpacity>
);
})}
</View>
);
}The state object tells which tab is active and the list of tabs.
The navigation object lets you move between tabs.
function SimpleTabBar({ state, navigation }) {
return (
<View style={{ flexDirection: 'row' }}>
{state.routes.map((route, index) => (
<TouchableOpacity
key={route.key}
onPress={() => navigation.navigate(route.name)}
style={{ flex: 1, padding: 10 }}
>
<Text>{route.name}</Text>
</TouchableOpacity>
))}
</View>
);
}function ColoredTabBar({ state, navigation }) {
return (
<View style={{ flexDirection: 'row' }}>
{state.routes.map((route, index) => {
const isFocused = state.index === index;
return (
<TouchableOpacity
key={route.key}
onPress={() => navigation.navigate(route.name)}
style={{
flex: 1,
padding: 10,
backgroundColor: isFocused ? 'skyblue' : 'white'
}}
>
<Text style={{ color: isFocused ? 'white' : 'black' }}>{route.name}</Text>
</TouchableOpacity>
);
})}
</View>
);
}This app shows two tabs: Home and Settings. The custom tab bar changes the background color of the active tab to purple and text to white. Other tabs have white background and black text.
import React from 'react'; import { View, Text, TouchableOpacity } from 'react-native'; import { NavigationContainer } from '@react-navigation/native'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; function HomeScreen() { return <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}><Text>Home Screen</Text></View>; } function SettingsScreen() { return <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}><Text>Settings Screen</Text></View>; } function MyTabBar({ state, descriptors, navigation }) { return ( <View style={{ flexDirection: 'row', backgroundColor: '#eee' }}> {state.routes.map((route, index) => { const isFocused = state.index === index; const onPress = () => { const event = navigation.emit({ type: 'tabPress', target: route.key, canPreventDefault: true }); if (!isFocused && !event.defaultPrevented) { navigation.navigate(route.name); } }; return ( <TouchableOpacity key={route.key} onPress={onPress} style={{ flex: 1, padding: 15, backgroundColor: isFocused ? '#6200ee' : '#fff' }} accessibilityRole="button" accessibilityState={isFocused ? { selected: true } : {}} accessibilityLabel={descriptors[route.key].options.tabBarAccessibilityLabel} testID={descriptors[route.key].options.tabBarTestID} > <Text style={{ color: isFocused ? 'white' : 'black', textAlign: 'center' }}>{route.name}</Text> </TouchableOpacity> ); })} </View> ); } const Tab = createBottomTabNavigator(); export default function App() { return ( <NavigationContainer> <Tab.Navigator tabBar={props => <MyTabBar {...props} />}> <Tab.Screen name="Home" component={HomeScreen} /> <Tab.Screen name="Settings" component={SettingsScreen} /> </Tab.Navigator> </NavigationContainer> ); }
Always add accessibility props like accessibilityRole and accessibilityState for better screen reader support.
You can add icons or badges inside the tab buttons to improve UI.
Remember to handle the tabPress event to allow default navigation behavior.
Custom tab bars let you design your own bottom navigation look and feel.
You get the current tab info from state and control navigation with navigation.
Use TouchableOpacity or similar to make tabs clickable.
Practice
Solution
Step 1: Understand what a tab bar does
A tab bar shows navigation options at the bottom of the screen for switching between views.Step 2: Identify the role of a custom tab bar
A custom tab bar lets you change how these tabs look and behave, instead of using the default style.Final Answer:
To create a personalized look and behavior for the bottom navigation tabs -> Option CQuick Check:
Custom tab bar = personalized navigation UI [OK]
- Thinking it replaces navigation logic entirely
- Assuming it disables navigation
- Confusing it with data fetching
Solution
Step 1: Identify clickable components
TouchableOpacity is designed to respond to touch events and provide feedback.Step 2: Match with tab interaction needs
Tabs need to be clickable to switch screens, so TouchableOpacity is the right choice.Final Answer:
TouchableOpacity -> Option BQuick Check:
Clickable tab = TouchableOpacity [OK]
- Using View which is not clickable by default
- Choosing TextInput which is for text input
- Using ScrollView which is for scrolling content
state.index === 1 ? 'blue' : 'gray'What does this expression do?
Solution
Step 1: Understand the ternary expression
The expression checks if state.index equals 1; if true, it returns 'blue', else 'gray'.Step 2: Relate to tab color logic
This means the tab at index 1 is highlighted blue when active, others are gray.Final Answer:
Sets the tab color to blue if it is the active tab, otherwise gray -> Option DQuick Check:
state.index === 1 ? 'blue' : 'gray' = active tab color logic [OK]
- Thinking it always returns gray
- Assuming it causes syntax error
- Confusing the condition with app start
const CustomTabBar = ({ state, navigation }) => {
return (
<View>
{state.routes.map((route, index) => (
<TouchableOpacity
key={index}
onPress={() => navigation.navigate(route.name)}
>
<Text>{route.name}</Text>
</TouchableOpacity>
))}
</View>
);
};Solution
Step 1: Review accessibility best practices
TouchableOpacity should have accessibilityRole and accessibilityState for screen readers.Step 2: Check other parts of code
Using index as key is not ideal but won't cause navigation errors; navigation.navigate usage is correct.Final Answer:
Missing accessibility props for TouchableOpacity -> Option AQuick Check:
Accessibility props missing = error [OK]
- Ignoring accessibility props
- Thinking index key breaks navigation
- Assuming navigation.navigate is wrong here
state and navigation to achieve this?Solution
Step 1: Identify correct state usage
The active tab index is in state.index, not navigation.state or state.activeTab.Step 2: Identify correct navigation method
navigation.navigate(route.name) is used to switch tabs; goBack or push are not appropriate here.Step 3: Apply styling based on active tab
Compare current index with tab index to apply bold style and change icon color.Final Answer:
Use state.index to check active tab, and navigation.navigate(route.name) on press; style label bold if active -> Option AQuick Check:
state.index + navigation.navigate = correct tab control [OK]
- Using wrong property like navigation.state.index
- Using navigation.goBack instead of navigate
- Using state.activeTab which doesn't exist
Ready to prove it?
Pass the test and this pattern moves unknown
