'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
tabBarIcon
is a property onnavigationOptions
, so we know we can use it on our screen components, but in this case chose to put it in thecreateBottomTabNavigator
configuration in order to centralize the icon configuration for convenience.tabBarIcon
is a function that is given thefocused state
,tintColor
, andhorizontal
param, which is a boolean. If you take a peek further down in the configuration you will seetabBarOptions
andactiveTintColor
andinactiveTintColor
. These default to the the iOS platform defaults, but you can change them here. ThetintColor
that is passed through to thetabBarIcon
is either the active or inactive one, depending on thefocused
state (focused is active). The orientation statehorizontal
is true when the device is in landscape, otherwise isfalse
for portrait.- Read the full API reference for further information on
createBottomTabNavigator
configuration 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 |