Home > Enterprise >  How to dynamically create Stack.Screen ? - I can't navigate to dynamically created Screens
How to dynamically create Stack.Screen ? - I can't navigate to dynamically created Screens

Time:05-19

I have an object that I am trying to loop through to create Screens dynamically. I have a Drawer that contains a list of items that each have an onPress function to navigate to those dynamically created Screens. However, when I press an item from the Drawer, nothing happens. I am wondering if my loop is incorrect, but I can't determine why; if i console.log, I can see all the appropriate info needed to create the right Screen. If I create Screens manually, the onPress does navigate to the appropriate Screen

This is the App.js

const drawerItemsMain = [
  {
    key: 'Pastry',
    title: 'Pastry',
    routes: [
      {nav: 'MainDrawer', routeName: "LemonBar", title: 'LemonBar'},
    ],
  },
]

const MainDrawerNavigation = () => {
    return(
        <Drawer.Navigator drawerContent={(props) => <CustomDrawerContent drawerItems={drawerItemsMain} {...props}/>}>
            <Drawer.Screen name="Home" component={HomeScreen} />
            {
                drawerItemsMain.map((item) => {
                    item.routes.map((route) => {
                        console.log(route.title)
                        return (
                            <Drawer.Screen 
                                key={route.title}
                                name={route.title}
                                component={route.routeName}
                                options={{ title: route.title }}
                            />
                        )
                    })
                })
            }
            //<Drawer.Screen name="LemonBar" component={LemonBar} /> //this works
        </Drawer.Navigator>
    )
}

const App = () => {
  return (
    <NavigationContainer>
        <Stack.Navigator screenOptions={{headerShown: false}}>
            <Stack.Screen name="MainDrawer" component={MainDrawerNavigation} />
        </Stack.Navigator>
    </NavigationContainer>
  );
}

Thank you in advance for any help

CodePudding user response:

I think uou have to pass the id or link of appropriate screen for the onPress .

CodePudding user response:

You can definitely create screen dynamically, however you have two array.map functions, one returns screens, and the englobing one returns nothing.

try

{drawerItemsMain.reduce((res, group) => [
   ...res, 
   ...(group.routes.map((route) => (
     <Drawer.Screen 
       key={route.title}
       name={route.title}
       component={route.routeName}
       options={{ title: route.title }}
     />
   ))
  ],
  [], // reducer inital state
)}

( Nesting .map in a .map would have returned a an array of array of screens. using .reduce here to have a flat array of screens )

CodePudding user response:

You have forgotten to add a return statement. The following fixes the issue.

<Drawer.Navigator drawerItems={drawerItemsMain}>
    <Drawer.Screen name="Home" component={HomeScreen} />
            {
                drawerItemsMain.map((item) => {
                    return item.routes.map((route) => {
                        console.log(route.title)
                        return (
                            <Drawer.Screen 
                                key={route.title}
                                name={route.title}
                                component={route.routeName}
                                options={{ title: route.title }}
                            />
                        )
                    })
                })
            }
        </Drawer.Navigator>

Notice as well that the navigation framework won't create the actual screen component in means of a JSX component. Hence, there must exist a JSX component named LemonBar in your project which is also imported in the file in which your drawer is initialized.

In that sense there is no "dynamic creation of screens in terms of components". If the components are imported and exist in your project, then you can add them to the drawer navigator as a screen using the above snippet.

  • Related