简体   繁体   中英

In react-native, how to add active class to selected menu option

I have the following menu options in the following structure:

const menuOptions = [
  {
    route: 'RegisterStack',
    label: 'Register',
    size: 25,
  },
  {
    route: 'LoginStack',
    label: 'Login',
    size: 25,
  },
  {
    route: 'DashboardStack',
    label: 'Dashboard',
    size: 25,
  }
];

and here's my remaining code with component state and the rest of the code:

const [activeLink, setActiveLink] = useState('');
const navigation = useNavigation();

<View>
    {menuOptions.map((stack, index) => {
        return (
        <TouchableOpacity
            key={index}
            style={[
            styles.menuStyle, 
            index === activeLink 
                ? {backgroundColor: 'red'} 
                : {backgroundColor: 'white'}
            ]}
            onPress={() => navigation.navigate(stack.route)}>
            <Icon
            name={stack.icon}
            color={stack.color}
            size={stack.size}
            style={{
            marginRight: mainMenuOpen ? '10%' : 0,
            }}
            onPress={() => setActiveLink(index)}
            />
            <Text style={{width: '70%', fontWeight: '500'}}>
            {stack.label}
            </Text>
        </TouchableOpacity>
        );
    })}
</View>

With the current code, I can see active class taking place but it seems to broke the navigation and won't route to a different page when click on it. The navigation starts working fine when I remove the following onPress method from Icon onPress={() => setActiveLink(index)} .

Can someone please help me how can I make this work?

The problem here is that you are nesting two pressables. The touch event will be caught by onPress of the Icon component . This is also the reason why the navigation starts working when you remove the inner onPress function.

It seems to me that you either want setActiveLink to be triggered if we press on the Icon only or you want setActiveLink to be triggered and then navigate to the desired screen at the same time.

In the second case you just need one onPress function for the outer component.

<TouchableOpacity
            key={index}
            style={[
            styles.menuStyle, 
            index === activeLink 
                ? {backgroundColor: 'red'} 
                : {backgroundColor: 'white'}
            ]}
            onPress={() => {
               setActiveLink(index)
               navigation.navigate(stack.route)
            }}>
            <Icon
            name={stack.icon}
            color={stack.color}
            size={stack.size}
            style={{
            marginRight: mainMenuOpen ? '10%' : 0,
            }}
            />
            <Text style={{width: '70%', fontWeight: '500'}}>
            {stack.label}
            </Text>
 </TouchableOpacity>

If you want two separate things to happen, eg setActiveLink on Icon press only and navigate on stack.label press only, then you need to reorganize your component. You could create a parent view which layouts the components in a row without nesting two pressables.

// you still need to apply the desired styles...
<View>
    <Pressable onPress={() => setActiveLink(index)}>
      <Icon
            name={stack.icon}
            color={stack.color}
            size={stack.size}
      />
    </Pressable>
    <TouchableOpacity
            key={index}
            onPress={() => {
               navigation.navigate(stack.route)
            }}>
            <Text style={{width: '70%', fontWeight: '500'}}>
                {stack.label}
            </Text>
    </TouchableOpacity>
</View>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM