Reputation: 720
Even though this document (https://facebook.github.io/react-native/docs/gesture-responder-system.html) states, that touch events are passed down to the children and are only consumed by a parent, if the child doesn't react on the event, I face the issue, that a TouchableOpacity nested inside another TouchableOpacity doesn't react properly on touches.
My structure is like follows
<ScrollView>
<TouchableOpacity onPress={() => console.log('This is printed always')}>
<View>
<Text>I can click here</Text>
<TouchableOpacity onPress={() => console.log('This is printed never')}>
<Text>I can click here but the outer onPress is called instead of the inner one</text>
</TouchableOpacity>
</View>
</TouchableOpacity>
</ScrollView>
The same happens for Buttons inside TouchableOpacitys: Clicking the Buttons calls the onPress method of the parent TouchableOpacity
Am I overseeing something?
Upvotes: 28
Views: 22533
Reputation: 77
Use the following (e.stopPropagation()) within the nested TouchableOpacity: Your code will look like such:
<TouchableOpacity
style={styles.EmailContainer}
onPress={() => setShow(!show)}>
<Text>From</Text>
<Text style={styles.Email}>
{requestMoney?.email}
</Text>
{show && (
<>
<TouchableOpacity
onPress={(e) => {
e.stopPropagation();
console.log(
'Selection one',
);
}}>
<Text>Selection one</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={(e) => {
e.stopPropagation();
console.log(
'Selection Two',
);
}}>
<Text>Selection one</Text>
</TouchableOpacity>
</>
)}
</TouchableOpacity>
Upvotes: 0
Reputation: 1
I had the same problem (non-clickable nested touchable opacity) but with iOS only, and strangely it was fixed simply by rearranging the order of JSX elements within the parent container touchable opacity.
I had a nested absolute position touchable opacity declared first inside a container touchable opacity. Then, I had a flex-row view declared afterwards (also inside the parent container). I moved the JSX for the nested touchable opacity below the JSX for the flex-row view and it worked!
I had no idea that the ordering in JSX would matter.
Upvotes: 0
Reputation: 2383
Change import of Touchable opacity from:
import { TouchableOpacity } from 'react-native-gesture-handler';
to the following, and it will now all be fine:
import { TouchableOpacity } from 'react-native';
Upvotes: 47
Reputation: 61
Writing here to make it a little more prominent.
It could be the nested TouchableOpacity
is being imported from something different from the parent one as mentioned by
@EliezerSteinbock. This could be quite possible as many of us use auto-imports on visual code or other IDE.
Sadly I missed her comment the first time round, so hopefully this would help someone else
Upvotes: 6
Reputation: 105
You could just use TouchableWithoutFeedback
to wrap inner TouchableOpacity
.
Something like:
<TouchableOpacity onPress={() => console.log('This is printed always')}>
<View>
<Text>I can click here</Text>
<TouchableWithoutFeedback>
<TouchableOpacity onPress={() => console.log('This is printed never')}>
<Text>I can click here but the outer onPress is called instead of the inner one</text>
</TouchableOpacity>
</TouchableWithoutFeedback>
</View>
</TouchableOpacity>
Upvotes: 8