'Get the current active screen route of the tab navigator in react navigation
This is my navigation stack using react navigation v3.2.1:
I have a switch navigator to switch to Authentication navigation stack and Authenticated App stack.
The App stack is made using a bottom tab navigator.
I would like to use a custom component for the tab navigator.
How do I get the current routeName of the tab navigator when using createBottomTabNavigator and a custom tabBarComponent.
Eg:
- Suppose the tab navigation stack has 2 navigation screens, i.e., Home and Chat.
- Inside the custom BottomBar, how do I check if the focused/active/current routeName is Home/Chat so that I can change the style of icons respectively?
AppContainer.js
const switchStack = createSwitchNavigator({
AuthLoading: AuthLoadingScreen,
App: AppStack,
Auth: AuthStack
}, {
initialRouteName: 'AuthLoading',
})
export default createAppContainer(switchStack)
AppStack.js
const AppStack = createBottomTabNavigator({
Home: {
screen: HomeStack,
},
Chat: {
screen: ChatStack
},
}, {
initialRouteName: 'Home',
activeColor: '#f0edf6',
inactiveColor: '#3e2465',
shifting: false,
barStyle: {
backgroundColor: '#694fad',
},
labeled: false,
tabBarComponent: ({navigation}) => <BottomBar navigation={navigation}/>
})
export default AppStack
BottomBar.js
export default class BottomBar extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<View style={styles.container}>
<IconComponent routeName={'Home'}/>
<IconComponent routeName={'Chat'}/>
</View>
)
}
}
IconComponent.js
export default class IconComponent extends React.Component {
constructor(props) {
super(props)
}
...
render() {
let IconComponent
let iconName
let iconSize = 25
switch (this.props.routeName) {
case 'Home':
IconComponent = MaterialCommunityIcons
// iconName = `home${focused ? '' : '-outline'}`;
iconName = `home`;
break
case 'Chat':
IconComponent = AntDesign
iconName = `message1`
iconSize = 22
break
}
let tintColor = 'green'
// if focused Home is current tab screen then change style eg. tint color.
// similary if current tab screen is Chat, then change style.
return (
<Animated.View
style={[
styles.container,
{
opacity: this.opacity
}
]}
>
<IconComponent name={iconName} size={iconSize} color={tintColor}/>
</Animated.View>
)
}
}
Solution 1:[1]
navigation object of your custom BottomBar has an index that hold the current active screen index
tabBarComponent: ({navigation}) => <BottomBar navigation={navigation}/>
navigation.state.index
If Home screen is active >> navigation.state.index would be 0 If Chat screen is active >> navigation.state.index would be 1 ...etc
Solution 2:[2]
Rather than setting a complete new tabBarComponent for icons you can use tabBarIcon property to set the icons. You can find an example on Tab Navigation Docs
tabBarIconis a property onnavigationOptions, so we know we can use it on our screen components, but in this case chose to put it in thecreateBottomTabNavigatorconfiguration in order to centralize the icon configuration for convenience.tabBarIconis a function that is given thefocused state,tintColor, andhorizontalparam, which is a boolean. If you take a peek further down in the configuration you will seetabBarOptionsandactiveTintColorandinactiveTintColor. These default to the the iOS platform defaults, but you can change them here. ThetintColorthat is passed through to thetabBarIconis either the active or inactive one, depending on thefocusedstate (focused is active). The orientation statehorizontalis true when the device is in landscape, otherwise isfalsefor portrait.- Read the full API reference for further information on
createBottomTabNavigatorconfiguration options.
Example (From the docs)
export default createBottomTabNavigator(
{
Home: HomeScreen,
Settings: SettingsScreen,
},
{
defaultNavigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, horizontal, tintColor }) => {
const { routeName } = navigation.state;
let IconComponent = Ionicons;
let iconName;
if (routeName === 'Home') {
iconName = `ios-information-circle${focused ? '' : '-outline'}`;
// Sometimes we want to add badges to some icons.
// You can check the implementation below.
IconComponent = HomeIconWithBadge;
} else if (routeName === 'Settings') {
iconName = `ios-options${focused ? '' : '-outline'}`;
}
// You can return any component that you like here!
return <IconComponent name={iconName} size={25} color={tintColor} />;
},
}),
tabBarOptions: {
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
},
}
);
Solution 3:[3]
You can with navigation.state.routeName
tabBarComponent: ({navigation}) => <BottomBar navigation={navigation} currentRouteName={navigation.state.routeName} />
Or Better still you can do something like this:
const TabNavigator = createBottomTabNavigator({
Home: Home,
Chat: Chat
},
{
defaultNavigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, horizontal, tintColor }) => {
if (navigation.state.routeName === 'Home') {
return <Icon name='ios-home' size={30} color={tintColor} />
} else if (navigation.state.routeName === 'Chat') {
return <Icon name='ios-heart' size={30} color={tintColor} />
}
},
tabBarOptions: {
activeTintColor: '#2BEDBA',
inactiveTintColor: '#FAFAFA',
style: { backgroundColor: '#000', paddingTop: 5 }
},
})
});
Solution 4:[4]
Using a functional component with React Navigation 5.x. You can use the useIsFocused hook.
import { useIsFocused } from "@react-navigation/native";
Usage: In each of the tab screens that you want to detect if they are the currently active or focused.
const isFocused = useIsFocused();
if (isFocused) {
// the screen is currently focused
// your code here
}
Docs: https://reactnavigation.org/docs/function-after-focusing-screen/
Solution 5:[5]
As @Biskrem Muhammad suggested, this works:
export function SignUp(props: TSignupProps) {
const { navigation, route } = props;
console.log('Im in screen:', route.name)
.
.
.
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | bennygenel |
| Solution 3 | |
| Solution 4 | Hackman |
| Solution 5 | jonyB |
