Search code examples
react-nativereact-navigationreact-native-navigationreact-navigation-v5react-navigation-bottom-tab

How to conditionaly change screen buttons in React Native bottom tab?


I have a bottom tab with buttons A,B,C,D,E.

  • When I'm on screen A I want the tab to show B,C,D,E buttons but not button A.
  • When I'm on screen B I want the tab to show A,C,D,E buttons but not button B.
  • When I'm on other screens I want to show A,C,D,E buttons or B,C,D,E (depends witch I pick A or B).

I have searched all over google, stackoverflow, youtube and have not seen a solution to this need.

  • I'm using react navigation v5.

I have tried in many ways and somethings like this:

<Tab.Screen name="A" component={A}
   options={
     ()=>{
       tabBarButton:(props)=>{
         if(isScreen("A")){
            return null;
         }else{
            return <TouchableOpacity {...props}/>
         }
       }     
     }
   }
/>

<Tab.Screen name="B" component={B}
   options={
     ()=>{
       tabBarButton:(props)=>{
         if(isScreen("A")){
            return <TouchableOpacity {...props}/>
         }else{
            return null;
         }
       }     
     }
   }
/>

But this gives me not the correct behavior even though it does not error out!!

If you guys do not understand the problem let me know and i will make the problem more concrete.

If you do not have time to explain the solution at least give me a code sample or an article or something for this use case.

PLZ HELP.


Solution

  • You will have to create a custom tab bar for this and conditionally show the labels.

    You can see the reference for the custom tab bar here https://reactnavigation.org/docs/bottom-tab-navigator/#tabbar

    You will have to create something like below (I have modified the sample code from the documentation)

    function MyTabBar({ state, descriptors, navigation }) {
    
      //Condition to decide the tab or not
      const shouldDisplay = (label, isFocused) => {
        if (label === 'A' && isFocused) return false;
        else if (label === 'B' && isFocused) return false;
        else return true;
      };
    
      return (
        <View style={{ flexDirection: 'row' }}>
          {state.routes.map((route, index) => {
            const { options } = descriptors[route.key];
            const label =
              options.tabBarLabel !== undefined
                ? options.tabBarLabel
                : options.title !== undefined
                ? options.title
                : route.name;
    
            const isFocused = state.index === index;
    
            if (!shouldDisplay(label, isFocused)) return null;
    
            const onPress = () => {
              const event = navigation.emit({
                type: 'tabPress',
                target: route.key,
              });
    
              if (!isFocused && !event.defaultPrevented) {
                navigation.navigate(route.name);
              }
            };
    
            const onLongPress = () => {
              navigation.emit({
                type: 'tabLongPress',
                target: route.key,
              });
            };
    
            return (
              <TouchableOpacity
                accessibilityRole="button"
                accessibilityState={isFocused ? { selected: true } : {}}
                accessibilityLabel={options.tabBarAccessibilityLabel}
                testID={options.tabBarTestID}
                onPress={onPress}
                onLongPress={onLongPress}
                style={{ flex: 1 }}>
                <Text style={{ color: isFocused ? '#673ab7' : '#222' }}>
                  {label}
                </Text>
              </TouchableOpacity>
            );
          })}
        </View>
      );
    }
    

    You can see the code in the below snack https://snack.expo.io/@guruparan/customtabs