The Material Bottom Navigation is designed to be very customizable and pluggable. Instead of a big configuration object, it uses React's Render Props to render smaller, customizable Components. If you're new to React and/or Render Props, read the article on render props first – or simply dive into the Bottom Navigation and learn it by doing.
You will use render props for
- rendering a Tab (FullTab, IconTab or ShiftingTab).
- rendering an Icon.
- rendering a Badge.
The BottomNavigation receives two main props:
tabsis an array of tab objects. Read more about required keys in this object in the documentation for the tabs arrayrenderTabis a Render Prop which will be called for each tab, and you have to return a Component.
import { View } from 'react-native'
import BottomNavigation from 'react-native-material-bottom-navigation'
export default class App extends React.Component {
tabs = [
{
key: 'games',
icon: 'gamepad-variant',
label: 'Games',
barColor: '#388E3C',
pressColor: 'rgba(255, 255, 255, 0.16)'
},
{
key: 'movies-tv',
icon: 'movie',
label: 'Movies & TV',
barColor: '#B71C1C',
pressColor: 'rgba(255, 255, 255, 0.16)'
},
{
key: 'music',
icon: 'music-note',
label: 'Music',
barColor: '#E64A19',
pressColor: 'rgba(255, 255, 255, 0.16)'
}
]
render() {
return (
<View>
<BottomNavigation
renderTab={this.renderTab}
tabs={this.tabs}
/>
</View>
)
}
renderTab = () => {
return <View />
}
}This will render just the Bottom Navigation without any Tabs – because we're just returning a blank View Component.
Some notes on the tabs Array:
keyis required and should be a unique identifier for this tab.barColordefines the background color of the Bottom Navigation when this Tab is active.pressColordefines the color of the press feedback.- The other keys (
iconandlabel) are just payload, defined by you. You will use those two keys in the next section.
Now we will render a Tab instead of a blank View:
import { View } from 'react-native'
import BottomNavigation, {
FullTab
} from 'react-native-material-bottom-navigation'
export default class App extends React.Component {
tabs = [
{
key: 'games',
icon: 'gamepad-variant',
label: 'Games',
barColor: '#388E3C',
pressColor: 'rgba(255, 255, 255, 0.16)'
},
{
key: 'movies-tv',
icon: 'movie',
label: 'Movies & TV',
barColor: '#B71C1C',
pressColor: 'rgba(255, 255, 255, 0.16)'
},
{
key: 'music',
icon: 'music-note',
label: 'Music',
barColor: '#E64A19',
pressColor: 'rgba(255, 255, 255, 0.16)'
}
]
render() {
return (
<View>
<BottomNavigation
renderTab={this.renderTab}
tabs={this.tabs}
/>
</View>
)
}
renderTab = ({ tab, isActive }) => {
return (
<FullTab
key={tab.key}
isActive={isActive}
label={tab.label}
renderIcon={this.renderIcon}
/>
)
}
renderIcon = ({ isActive }) => {
return <View />
}
}The renderTab method will be called for each object in our tabs array. The method contains an object as parameter, with tab and isActive.
tabis the tab object, which is currently being rendered. This is the exact same object from ourtabsarray.isActivetells us if the Tab is currently active.
We use those informations to return a FullTab, which displays a label and an Icon. The Icon is once again a render prop, similar to the renderTab prop. For now we just return a blank View, as we did earlier for the Tab.
Instead of a FullTab, you can also use:
- an
IconTabwhich displays just an Icon. - a
ShiftingTab, which is a FullTab, but the active tab is bigger than the other tabs. - a Component you created yourself! As a starting point, take a look at the implementation of the IconTab.
The Icon can be any Component you want to use, for example @expo/vector-icons. In fact, the Material Bottom Navigation doesn't include an own Icon Component.
As you see above, the renderIcon prop only contains an object as argument with the isActive key. We pass more arguments to renderIcon using something called a Thunk: a function returning a function. This sounds complicated, but are just two small changes:
// ...
renderTab = ({ tab, isActive }) => {
return (
<FullTab
key={tab.key}
isActive={isActive}
label={tab.label}
renderIcon={this.renderIcon(tab.icon)}
/>
)
}
renderIcon = iconName => ({ isActive }) => {
return <Icon size={24} color="white" name={iconName} />
}
// ...And you're finished! You now should have a fully functional Bottom Navigation with nice animations.
The Badge is a render prop on the Tab Component. You can render anything inside a badge: e.g. a white dot, text, or simply nothing.
import BottomNavigation, {
FullTab,
Badge
} from 'react-native-material-bottom-navigation'
// ...
renderBadge = badgeCount => {
return <Badge>{badgeCount}</Badge>
}
renderTab = ({ tab, isActive }) => {
return (
<FullTab
showBadge={tab.badgeCount > 0}
renderBadge={this.renderBadge(tab.badgeCount)}
key={tab.key}
isActive={isActive}
label={tab.label}
renderIcon={this.renderIcon(tab.icon)}
/>
)
}You have two new props to render a badge:
renderBadge, the render prop to render a badgeshowBadgewhich defines a condition if the badge should be rendered.
Check out the API Documentations of the different Tabs and for the Badge to see more informations and additional props for Badges.
To use the Bottom Navigation as Controlled Component, you can use two additional props:
activeTab: the key of the currently active tab.onTabPress: event handler when a Tab is being pressed, called with the key of the new and old tab as parameter.
import BottomNavigation from 'react-native-material-bottom-navigation'
export default class App extends React.Component {
state = {
activeTab: 'games'
}
handleTabPress = (newTab, oldTab) => {
this.setState({ activeTab: newTab })
}
render() {
return (
<View>
<BottomNavigation
activeTab={this.state.activeTab}
onTabPress={this.handleTabPress}
renderTab={/* ... */}
tabs={/* ... */}
/>
</View>
)
}
}If you want to display different contents on your screen depending on the active tab, you can use the onTabPress prop and save the active tab in your state. Check out the Chapter Controlled Component.
You most likely want to use this together with a navigation library, e.g. React Navigation or React Native Navigation.