Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the current active screen route of the tab navigator in react navigation

This is my navigation stack using react navigation v3.2.1:

  1. I have a switch navigator to switch to Authentication navigation stack and Authenticated App stack.

  2. The App stack is made using a bottom tab navigator.

  3. 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:

  1. Suppose the tab navigation stack has 2 navigation screens, i.e., Home and Chat.
  2. 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>
        )
    }
}
like image 776
Kakar Avatar asked Mar 16 '19 16:03

Kakar


3 Answers

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 }
        },
    })
});
like image 111
LordKiz Avatar answered Sep 22 '22 13:09

LordKiz


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

like image 38
Hend El-Sahli Avatar answered Sep 19 '22 13:09

Hend El-Sahli


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/

like image 32
Hackman Avatar answered Sep 21 '22 13:09

Hackman