Search code examples
react-nativereact-propsstack-navigatorreact-navigation-bottom-tab

How to send props from createBottomTabNavigation to every tab screen?


I am using createBottomTabNavigation and I have 4 screens which I can access by pressing the tab bar screen in the bottom of my screen. I am also using Stack Navigation to display the title of the screen there and also all screens have the same settings icon.

I could make the same function in every screen that takes care of onPress event on the Settings icon but that is repetitive and I don't want to do it.

My question is - is there a way for me to pass a function as a props from the App component which holds the bottom navigation to every screen?

App screen code:

<NavigationContainer >
 <Tab.Navigator initialRouteName="Home"  tabBarOptions={{
       activeTintColor: '#FF9F0A',
       inactiveTintColor:'white',
       style: {
        backgroundColor:'#000000',//color you want to change
          borderTopWidth: 0,
          paddingTop:5,
          paddingBottom:5,
       },
      
     }}>
   <Tab.Screen name="Home" component={Home}  options={{
         tabBarLabel: 'HOME',
         tabBarIcon: ({ color, size }) => (
           <HomeTabIcon name="home" color={color} size={size} />
         ),
       }}/>
   <Tab.Screen name="Controls" component={Controls} options={{
         tabBarLabel: 'CONTROLS',
         tabBarIcon: ({ color, size }) => (
           <ControlsTabIcon name="controls" color={color} size={size} />
         ),
       }}/>
   <Tab.Screen name="Charging" component={Charging} options={{
         tabBarLabel: 'CHARGING',
         tabBarIcon: ({ color, size }) => (
           <ChargingTabIcon name="charging"  color={color} size={size}/>  
         ),
        
       }}/>

Charging screen:

   function Charging() {
  return (
    <View style={globalStyles.container}>
      <Text>Charging</Text>
      <StatusBar style="auto" />
    </View>
  );
}

export default function ChargingStackScreen() {
  return (
    <ChargingStack.Navigator>
      <ChargingStack.Screen name="CHARGING" component={Charging} options={{ 
         headerRight: () => (
          <View style={globalStyles.headerRight}>
            <SettingsIcon />
          </View>
        ),
        headerTitleAlign:'left',
        headerTintColor: 'white',
        headerTitleStyle: globalStyles.headerTitle,
        headerStyle:  globalStyles.header
         }}/>
    </ChargingStack.Navigator>
  );
}

Solution

  • So what I think you should do is have the header as a separate component, where you can use the useNavigation hook (assuming you're using the latest version of react-navigation), and have the settings button do the navigation you need. Then just render the header component once above the Tab.Navigator instead of rendering it on every screen.

    Something like:

    function Header(props){
        const navigation = useNavigation();
        
    
        // component code
        <SettingsButton onPress={() => navigation.navigate(whatever)}/>
    
    }
    

    And then I am pretty sure (not 100% though) that you can render it in your NavigationContainer, something like:

    <NavigationContainer >
    <Header/>
     <Tab.Navigator initialRouteName="Home"  tabBarOptions={{
      // rest of the code