moritzschaefer
moritzschaefer

Reputation: 720

Stacked TouchableOpacity inside another TouchableOpacity is not clickable

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

Answers (5)

PrinceMoMo
PrinceMoMo

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

Orky
Orky

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

Manoj Selvin
Manoj Selvin

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

BenC
BenC

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

A Kornytskyi
A Kornytskyi

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

Related Questions