How do I set custom drawer items to "focused" dynamically?
Asked Answered
P

1

8

My end goal here is to give a few drawer items custom background colors depending on a few states set elsewhere. I understand that in order to give unique background colors to drawer items, I need to set up custom drawer content. However, I am having an issue in which I cannot get the custom drawer icons to know if they are in focus or not.

I originally thought that I could just do a const [bHomeFocused, setbHomeFocused] = useState(false) (etc) and setting state on onPress and then setting the focused property on that, but when a bunch more drawer items come in, I think that sounds like an unwieldy solution.

I'm sure there is a simple answer that I'm missing, as non-custom DrawerItems have this functionality inherently...

import { Drawer } from 'react-native-paper'
import { createDrawerNavigator, DrawerNavigationProp, DrawerItem, DrawerContentScrollView, DrawerItemList, DrawerContentComponentProps, DrawerContentOptions } from '@react-navigation/drawer';

function CustomDrawerContent(props: DrawerContentComponentProps<DrawerContentOptions>) {

    return (
        <DrawerContentScrollView {...props}>
            <Drawer.Section>
                <DrawerItem
                    label="Dashboard"
                    labelStyle={{ color: colorTheme.normalText }}
                    icon={() => <Icon name="book" type="feather" size={26} color={colorTheme.normalText} />}
                    activeBackgroundColor={colorTheme.panel}
                    inactiveBackgroundColor={colorTheme.cyan}
                    onPress={() => {
                        props.navigation.navigate('Dashboard')
                    }}
                />
            </Drawer.Section>
            <DrawerItem
                label="Home"
                labelStyle={{ color: colorTheme.normalText }}
                icon={() => <Icon name="home" type="feather" size={26} color={colorTheme.normalText} />}
                activeBackgroundColor={colorTheme.panel}
                inactiveBackgroundColor={colorTheme.red}
                onPress={() => {
                    props.navigation.navigate('HomeStack')
                }}
            />
        </DrawerContentScrollView>
    );
}

export type DrawerParamList = {
    Dashboard: undefined;
    HomeStack: undefined;
};

export type DrawerProps<T extends keyof DrawerParamList> = {
    navigation: DrawerNavigationProp<DrawerParamList, T>;
    route: RouteProp<DrawerParamList, T>;
};

const AppDrawer = createDrawerNavigator<DrawerParamList>();

export default function MainDrawer({ route, navigation }: TopLevelStackProps<"MainDrawer">) {

    return (
        <AppDrawer.Navigator
            drawerStyle={globalStyles.drawer}
            drawerContent={
                (props) => <CustomDrawerContent {...props} />
            }
            drawerContentOptions={{
                labelStyle: { color: colorTheme.normalText },
                activeBackgroundColor: colorTheme.panel,
                inactiveBackgroundColor: colorTheme.background,
            }}
        >
            <AppDrawer.Screen
                name="Dashboard"
                component={Dashboard}
                options={{
                    unmountOnBlur: true,
                }}
            />
            <AppDrawer.Screen
                name="HomeStack"
                component={HomeStack}
                options={{
                    unmountOnBlur: true,
                }}
            />
        </AppDrawer.Navigator>
    );
}
Pena answered 16/8, 2020 at 2:48 Comment(0)
F
11

There's no focused prop which you can use to get the current focused route.

Instead, use the props that are received by the component by the DrawerNavigator. Check out this doc.

If you see the list of props passed to the drawerContent component, you can see the state prop. From the doc,

state - The navigation state of the navigator, state.routes contains list of all routes

So you can get the array of routes, and current index, which indicates which screen is currently focused. You can get the route name and compare it with the item name in your list.

const {state} = props
const {routes, index} = state; //Not sure about the name of index property. Do check it out by logging the 'state' variable.
const focusedRoute = routes[index];
   
Feeley answered 16/8, 2020 at 9:36 Comment(3)
That's great. I was able to extend this reasoning a bit to set the drawer item with focused={props.state.index === props.state.routes.findIndex(e => e.name === "Dashboard")} Works great!Pena
I did! Thank you. Unfortunately because I'm new here, my cast votes do not appear publicly.Pena
Not sure if something changed at some point, but there is a focused prop. This works: ` <Drawer.Screen name="My Profile" component={ProfileScreen} options={{ drawerIcon: ({ focused }) => <AntDesign name="profile" size={icons.size} color={focused ? drawerActiveTintColor : drawerInactiveTintColor} /> }} />`Frosted

© 2022 - 2025 — McMap. All rights reserved.