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.