I'm trying to do a dynamic Drawer, I have my StackItens (routes) settle like:
import React from 'react';
import Home from '../screens/home/Index';
import ATR from '../screens/atr/Index';
const stackNavigItems = [
{
group: 'Home',
name: 'Home',
component: Home,
icon: 'home',
iconType: 'FontAwesome',
label: 'Principal',
hideMenu: false,
screenComponent: props => {
return <Home {...props} />;
},
},
{
group: 'Home',
name: 'ATR',
component: ATR,
icon: 'book',
iconType: 'Ionicons',
label: 'ATR',
hideMenu: false,
screenComponent: props => {
return <ATR {...props} />;
},
},
];
export {stackNavigItems};
And In my Drawer Content I map these items and works fine. But when I map the same items inside the Navigator using this code:
<PaperProvider theme={theme}>
<AuthContext.Provider value={authContext}>
<NavigationContainer theme={theme}>
<Drawer.Navigator drawerContent={props => <DrawerContent {...props} />}>
{stackNavigItems.map(r => {
return (
<Drawer.Screen
key={r.name}
name={r.name}
component={({navigation}) => (
<Stack.Navigator
initialRouteName="Home"
headerMode="screen"
screenOptions={screenOptions}>
<Stack.Screen
name={r.name}
component={props => <r.screenComponent {...props} />}
options={{
title: r.label,
headerLeft: () => (
<Icon.Button
name="ios-menu"
size={IconStyles.size}
backgroundColor={AppStyles.color.main}
onPress={() => {
navigation.openDrawer();
}}
/>
),
}}
/>
</Stack.Navigator>
)}
/>
);
})}
</Drawer.Navigator>
</NavigationContainer>
</AuthContext.Provider>
</PaperProvider>
The app always show me this warning and the header double the size:
I tried so many ways passing a function "()" before the component and nothing works. If I disable the warning, the app works without show the warning but sometimes the header double the size while using like in the picture.
You can avoid using inline functions by creating an extra component and passing that normally and passing an id
of the navigation item via initialParams
to the extra component:
const StackNavigator = ({route}) => {
const navigationItem = stackNavigItems[route.params?.navigationItemId];
return (
<Stack.Navigator initialRouteName="Home" headerMode="screen">
<Stack.Screen
name={navigationItem.name}
component={navigationItem.screenComponent}
options={{
title: navigationItem.label,
headerLeft: () => null,
}}
/>
</Stack.Navigator>
);
};
function App() {
return (
<NavigationContainer>
<Drawer.Navigator drawerContent={(props) => null}>
{stackNavigItems.map((r) => {
return (
<Drawer.Screen
key={r.name}
name={r.name}
component={StackNavigator}
initialParams={{navigationItemId: r.id}}
/>
);
})}
</Drawer.Navigator>
</NavigationContainer>
);
}
So for this approach you do need to add an id
prop to the objects inside stackNavigItems
:
const stackNavigItems = [
{
id: 0,
group: 'Home',
name: 'Home',
component: Home,
icon: 'home',
iconType: 'FontAwesome',
label: 'Principal',
hideMenu: false,
screenComponent: (props) => {
return <Home {...props} />;
},
},
{
id: 1,
group: 'Home',
name: 'ATR',
component: ATR,
icon: 'book',
iconType: 'Ionicons',
label: 'ATR',
hideMenu: false,
screenComponent: (props) => {
return <ATR {...props} />;
},
},
];
I've left out some unrelated code, to make this example more readable.