Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Show a tab bar item or not based on Redux state in React Native

I've got a React Native app with React Navigation and I need to show or hide a tab based on Redux state. I'm using createBottomTabNavigator and have written this:

function createTabNavigator(props:TabNavigatorProps){
  debugger;
  const isClient = WHAT_TO_PUT_HERE??
  const tabs = isClient
  ? {
   //something
  } 
  : {
    //something else
  } 
  return createBottomTabNavigator(
   tabs,
    {
      defaultNavigationOptions: ({ navigation }) => ({
        tabBarIcon: ... ,
        tabBarLabel: ...,
      }
      tabBarComponent: (props) => customTabBar(props, isClient),
      tabBarOptions: {
        ...
      },
    });
};

My createTabNavigator works the way as intended if I manually set isClient to true or false, though I need this from redux state.

I've also tried connecting it, and mapStateToProps get called with the correct state, however it doesn't call createTabNavigator again so state changes aren't updated to my view hierarchy.

How can I add/remove a tab (and actually re-render altogether as that tab also involves some custom styling/rendering of the whole bar) based on Redux state?

like image 459
Can Poyrazoğlu Avatar asked Oct 28 '22 09:10

Can Poyrazoğlu


1 Answers

react-navigation does not provide any API to hide a tab from BottomTabNavigator.

However, it allows providing custom TabBarComponent. It also exposes BottomTabBar component which is the default TabBarComponent for BottomTabNavigator.

This BottomTabBar component takes a property getButtonComponent to get the component for rendering each tab. It is provided the tab details in argument and is expected to return component to be used for rendering that tab.

To achieve hiding of tabs dynamically, you provide your own function for getButtonComponent. Check the details of tab with your state to decide whether it should be visible or hidden. Return an 'empty component' if you want to hide it, else simply call the default.

/**** Custom TabBarComponent ****/
const BlackHole = (props) => []
let _TabBarComponent = (props) => {
  const getButtonComponent = (arg) => {
    const hide = props.hiddenTabs[arg.route.key];
    if (hide) {
      return BlackHole;
    }
    return props.getButtonComponent(arg)
  }
  return (<BottomTabBar {...props} getButtonComponent={getButtonComponent}/>);
};

const mapStateToProps = (state) => ({
  hiddenTabs: state.hiddenTabs
});

const TabBarComponent = connect(mapStateToProps)(_TabBarComponent);

/**** Navigation ****/
const TabNavigator = createBottomTabNavigator({
  Tab1: createStackNavigator({Screen1}),
  Tab2: createStackNavigator({Screen2}),
  Tab3: createStackNavigator({Screen3}),
}, {
  tabBarComponent: props => (
    <TabBarComponent {...props} style={{borderTopColor: '#605F60'}}/>
  )
});

See this snack for POC: https://snack.expo.io/BJ80uiJUH

like image 142
ckedar Avatar answered Nov 01 '22 21:11

ckedar