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, e.g. 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>