Passing params to tab navigator React Navigation 5
T

4

15

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>
    );
};
Tadeas answered 16/4, 2020 at 19:40 Comment(0)
A
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

Azerbaijan answered 16/4, 2020 at 22:12 Comment(4)
is this the only way? Its pretty common scenario to pass data to props. Why there is only param to pass initial props?Vicious
The route is undefined, inside PostsMainNav function.Tarrance
This seems a lot of work for just passing params to the tab navigator screens. Isn't there a better approach?Serena
Another way is to use method 2 from reactnavigation.org/docs/… using props: <Stack.Screen name="Home"> {(props) => <HomeScreen {...props} extraData={someData} />} </Stack.Screen>. Note that u need to remove component using this methodGus
B
13

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>
    );
};
Bidentate answered 19/2, 2021 at 13:4 Comment(1)
initialParams is never updated. So unless your params never change, this is a bad solution.Azerbaijan
E
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 >
);
Etrem answered 1/11, 2021 at 11:47 Comment(0)
D
0

From inside your Tab component you can get params of the parent navigation.

const NetworkUsersScreen = ({navigation}) => {
   const parent_navigation = navigation.getParent().getState();
   const network = parent_navigation.routes[parent_navigation.index].params.network;
}
Decanal answered 16/7 at 10:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.