14

I’m using materialTopTabs and it seems like this loads all the screens in the navigator once its mounted. I have a screen List and inside it a tab navigator with 2 screens: Posts and Users. These two screen both depend on params passed from List. However, i am only able to pass params to one of the screens using this method:

navigation.navigate('PostsTabNav', {
  params: {
    network: item,
  },
  screen: 'NetworkPosts' //or NetworkUsers
});

I have tried to pass the params to my navigator directly by doing this:

navigation.navigate('PostsTabNav', {
  network: item
});

The first option only allows me to pass to one screen. The second option allows me to access the params inside the navigator like this:

const PostsTabNav = createMaterialTopTabNavigator();
const PostsMainNav = (props) => {
    const temp = props.route.params.network; //params here

    return (
        <PostsTabNav.Navigator>
            <PostsTabNav.Screen name="NetworkPosts" component={NetworkPostsScreen} />
            <PostsTabNav.Screen name="NetworkUsers" component={NetworkUsersScreen} />
        </PostsTabNav.Navigator>
    );
};

Is there a way to pass temp to both my screens? If not is there a better way to handle this situation?

Here's the code for the StackNavigator

const NetworkListStackNav = createStackNavigator();
export const NetworksListNavigator = () => {
    return (
        <NetworkListStackNav.Navigator>
            <NetworkListStackNav.Screen name="List" component={ListScreen} />
            <NetworkListStackNav.Screen name="PostsTabNav" component={PostsMainNav} />
        </NetworkListStackNav.Navigator>
    );
};
abdi
  • 519
  • 1
  • 5
  • 16

3 Answers3

17

Pass params to the navigator and then expose it to the tabs using React Context.

Create a context in a separate file which you can import in both your navigator and screens:

export const NetworkContext = React.createContext();

Then provide the params in the context:

const PostsTabNav = createMaterialTopTabNavigator();

const PostsMainNav = ({ route }) => {
  return (
    <NetworkContext.Provider value={route.params.network}>
      <PostsTabNav.Navigator>
        <PostsTabNav.Screen name="NetworkPosts" component={NetworkPostsScreen} />
        <PostsTabNav.Screen name="NetworkUsers" component={NetworkUsersScreen} />
      </PostsTabNav.Navigator>
    </NetworkContext.Provider>
  );
};

In your screen component, use the context:

const network = React.useContext(NetworkContext);

Also see https://reactnavigation.org/docs/hello-react-navigation#passing-additional-props

satya164
  • 9,464
  • 2
  • 31
  • 42
  • 1
    is this the only way? Its pretty common scenario to pass data to props. Why there is only param to pass initial props? – Mohak Londhe Nov 07 '20 at 16:47
  • 1
    The route is undefined, inside PostsMainNav function. – rubimbura brian Nov 11 '20 at 06:51
  • 5
    This seems a lot of work for just passing params to the tab navigator screens. Isn't there a better approach? – Aldor Mar 26 '21 at 03:07
  • Another way is to use method 2 from https://reactnavigation.org/docs/hello-react-navigation#passing-additional-props using props: ` {(props) => } `. Note that u need to remove `component` using this method – TylerC Apr 25 '23 at 04:37
14

You can set initial params to your screens.

const PostsTabNav = createMaterialTopTabNavigator();
const PostsMainNav = (props) => {
    const temp = props.route.params.network
    return (
        <PostsTabNav.Navigator>
            <PostsTabNav.Screen name="NetworkPosts" component={NetworkPostsScreen} initialParams={network:temp}/>
            <PostsTabNav.Screen name="NetworkUsers" component={NetworkUsersScreen} initialParams={network:temp}/>
        </PostsTabNav.Navigator>
    );
};
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
Garvit Tyagi
  • 141
  • 1
  • 2
0
const Stack = createStackNavigator();
function AppNavigator(props) {
    const { cartCount } = props;
    return (
        <NavigationContainer>
              <Stack.Screen {...props} name="MainScreen" component={() => <MyTabs cartCounts={cartCount}></MyTabs>} options={{ headerShown: false }} countProp={cartCount} initialParams={{ 'count': cartCount }} />
             </Stack.Navigator>
        </NavigationContainer>
    )
}

function mapStateToProps(state) {
    return {
        cartCount: state.cart.cartCount,
    }
}

export default connect(mapStateToProps, {})(AppNavigator);

And your tab component like

function MyTabs(props) {
let cartCount = props.cartCounts;
return (
    <BottomTab.Navigator
        screenOptions={{
            tabBarStyle: { position: 'absolute' },
            tabBarStyle: styles.tabbarStyle
        }}>
        <BottomTab.Screen name="CartScreen" component={CartScreen} options={{ headerShown: false }}
            options={{
                headerShown: false,
                tabBarIcon: ({ focused, tintColor }) => (
                    <View style={styles.cartIconView}>
                        <Image
                            square
                            source={bottomCart}
                           
                        />
                        <Badge style={[GlobalStyles.badge, styles.count, {
                        }]}>
                            <Text style={[GlobalStyles.badgeText, styles.countText]}>{cartCount}</Text>
                        </Badge>
                    </View>
                ),
            }} />
    
    </BottomTab.Navigator >
);