To add an extra Drawer button that doesn't link to a route above or below a button in DrawerItemList is as easy as doing:
<Drawer.Navigator initialRouteName="Home" drawerContent={props => {
return (
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} />
<DrawerItem label="Logout" onPress={() => props.navigation.navigate("Login")} />
</DrawerContentScrollView>
)
}}>
<Drawer.Screen name="Home" component={Home}/>
<Drawer.Screen name="About" component={About} />
</Drawer.Navigator>
But now I need to add a custom button (like the Logout one, with a custom onPress that doesn't just go to a route, but navigates to Home and calls a couple of functions) between the Home and About buttons.
So my end button result with regards to the buttons on the Drawer should be:
-- Home
-- Custom
-- About
-- Logout
I'd need to somehow break up DrawerItemList but not sure how.
Any ideas how I can achieve this?
Snack can be found here
(Using react-navigation > v5)
To begin with , the code of DrawerItemList doesnt allow anything else except for screens to be there.
But its just another component that you have to pass.
So the easiest way to handle this would be to create your own version of DrawerItemList using the source code and have the option to pass a custom onPress function.
The custom component would look like this, I've commented the places that i modified.
import * as React from 'react';
import {
CommonActions,
DrawerActions,
DrawerNavigationState,
ParamListBase,
useLinkBuilder,
} from '@react-navigation/native';
import { DrawerItem } from '@react-navigation/drawer';
export default function CustomDrawerList({
state,
navigation,
descriptors,
activeTintColor,
inactiveTintColor,
activeBackgroundColor,
inactiveBackgroundColor,
itemStyle,
labelStyle,
}: Props) {
const buildLink = useLinkBuilder();
return state.routes.map((route, i) => {
const focused = i === state.index;
//Access the custom onPress that is passed as an option
const { title, drawerLabel, drawerIcon, onPress } = descriptors[route.key].options;
return (
<DrawerItem
key={route.key}
label={
drawerLabel !== undefined
? drawerLabel
: title !== undefined
? title
: route.name
}
icon={drawerIcon}
focused={focused}
activeTintColor={activeTintColor}
inactiveTintColor={inactiveTintColor}
activeBackgroundColor={activeBackgroundColor}
inactiveBackgroundColor={inactiveBackgroundColor}
labelStyle={labelStyle}
style={itemStyle}
to={buildLink(route.name, route.params)}
onPress={
//if onPress is available use that or call the usual navigation dispatch
// i also passed the navigation so that we can use it in our custom calls
onPress
? () => onPress(navigation)
: () => {
navigation.dispatch({
...(focused
? DrawerActions.closeDrawer()
: CommonActions.navigate(route.name)),
target: state.key,
});
}
}
/>
);
});
}
And the drawer would look like this, we pass the onPress as an option
<Drawer.Navigator
initialRouteName="Home"
drawerContent={(props) => {
return (
<DrawerContentScrollView {...props}>
<CustomDrawerList {...props} />
</DrawerContentScrollView>
);
}}>
<Drawer.Screen name="Home" component={PlaceholderPage} />
<Drawer.Screen name="Custom" component={PlaceholderPage} options={{
onPress:()=>alert(123)
}}/>
<Drawer.Screen name="About" component={PlaceholderPage} />
</Drawer.Navigator>
You can check the snack here https://snack.expo.io/@guruparan/custom-button-in-drawer
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With