25

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?

moritzschaefer
  • 681
  • 1
  • 8
  • 18
  • 7
    I ran into this issue when I was using a combination of TouchableOpacity from `react-native` and another one from `react-native-gesture-handler`. When using the same one twice it works as expected with the child being the only one to trigger the press event. – Eliezer Steinbock Sep 20 '19 at 14:07
  • 1
    @EliezerSteinbock thanks ... I was having same issue as you mentioned. – Samiksha Jagtap Oct 09 '19 at 06:14

4 Answers4

41

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';
stephen.hanson
  • 9,014
  • 2
  • 47
  • 53
Manoj Selvin
  • 2,247
  • 24
  • 20
  • 3
    I have the same imports from `react-native` but It didn't work. – AliRehman7141 Mar 13 '21 at 06:29
  • 2
    I had to add `react-native-gesture-handler` dependency in the project because it is a peer dependency of `@react-navigation/stack`. this is causing pain for auto-import as `TouchableOpacity` is now in two dependencies... – paradite Apr 02 '21 at 08:06
7

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>
Rishabh Bhatia
  • 1,019
  • 6
  • 14
A Kornytskyi
  • 95
  • 1
  • 3
5

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

BenC
  • 51
  • 1
  • 2
0

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.

Orky
  • 1
  • Welcome to Stack Overflow! Make sure to always include code on your answer! [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer) – William Brochensque junior Mar 03 '23 at 18:36
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 03 '23 at 18:36
  • This occurred because the `TouchableOpacity` was below the `View` in the component stack. The `View` was consuming the touch event before the inner `TouchableOpacity` had the chance to react to it. You could, alternatively, set a `zIndex` value in the style of the inner `TouchableOpacity` to fix the issue, without moving the order of the elements. – neutrino2039 Jul 12 '23 at 09:45