Shobika Babu
Shobika Babu

Reputation: 241

How to prevent parent click event in react native?

onParentClick = () => {
  console.log('Parent is triggered');
}

onChildClick = (event) => {
  event.stopPropagation();
  console.log('Child is triggered');
}
<TouchableWithoutFeedback onPress={()=> this.onParentClick()}>
  <View>
    <Text>How to prevent parent click event</Text>
    <TouchableOpacity onPress={(event)=> this.onChildClick(event)}>
      <Text> Click Me </Text>
    </TouchableOpacity>
  </View>
</TouchableWithoutFeedback>
<!-- edit description:- there was this end curly brace missing in above,
 however the snippet will not run because the language js will not 
support it and language html will not be able to format it correctly or run it.
(need to run the snippet on the react native environment like code-pen)  -->

Expected: On click of "Click Me", onChildClick() must be called

Issue: On click of "Click Me", onParentClick() is called.

How to prevent parents click event on click of "Click Me"?

Result which I get on click of parent is "Parent is triggered" and it works perfect.

But on click on child the result I get is "Parent is triggered".

I guess onChildClick() is not being triggered.

Upvotes: 19

Views: 18494

Answers (9)

Jlam
Jlam

Reputation: 1920

You'd want to use onTouchEnd not press

This would be the simplest answer:

use this on the inner view at the point where you want the propagation to stop

onTouchEnd={(e) => {
   e.stopPropagation()
}}

Upvotes: 0

Aaleen Mirza
Aaleen Mirza

Reputation: 125

You can simply set the parents pointerEvents property to 'box-none'. By doing so, the parent will not respond to touch events but its child views will get clicked.

  <TouchableWithoutFeedback
      pointerEvents={'box-none'}
  >
      <TouchableWithoutFeedback
          onPress={()=>{
              //onPress here will work
          }}
      />
  </TouchableWithoutFeedback>

Upvotes: 3

Kuza Grave
Kuza Grave

Reputation: 1574

Use TouchableOpacity from gesture handler

import { TouchableOpacity } from "react-native-gesture-handler";

then change your style to containerStyle instead

 <TouchableOpacity onPress={props.onPress} containerStyle={styles.container}>

everything should look good now...

Upvotes: 0

Mike Hamilton
Mike Hamilton

Reputation: 31

You need to "swallow" the click event somewhere. It could be in your outer TouchableWithoutFeedback (ie: change onPress={()=> this.onParentClick()} to onPress={(e) => e.preventDefault()} or you could wrap your TouchableOpacity in another touch handler, like below.

<TouchableWithoutFeedback onPress={()=> this.onParentClick()}>
  <View>
    <Text>How to prevent parent click event</Text>
    <TouchableWithoutFeedback onPress={(e) => e.preventDefault()}
      <TouchableOpacity onPress={(event)=> this.onChildClick(event)>
        <Text> Click Me </Text>
      </TouchableOpacity>
    </TouchableWithoutFeedback>
  </View>
</TouchableWithoutFeedback>

Upvotes: 3

H294
H294

Reputation: 166

A trigger method:

const childPresses = {}
if(canChildPress) {
  childPresses.onPress = (event) => {this.onChildClick(event)}
}

return <TouchableWithoutFeedback onPress={()=> this.onParentClick()}>
  <View>
    <Text>How to prevent parent click event</Text>
    <TouchableOpacity {...childPresses} >
      <Text> Click Me </Text>
    </TouchableOpacity>
  </View>
</TouchableWithoutFeedback>

Upvotes: 0

Dmitri Borohhov
Dmitri Borohhov

Reputation: 1613

Old question, but I faced the same issue and in my case, the problem was:

import {TouchableOpacity} from 'react-native';
import {TouchableWithoutFeedback} from 'react-native-gesture-handler';

This weird import happened due to automatic suggestion by eslint. Somehow these libraries don't play nicely together, so I changed the above to:

import {TouchableOpacity, TouchableWithoutFeedback} from 'react-native';

Upvotes: 24

Ammar Tariq
Ammar Tariq

Reputation: 847

I had the similar issue, resolved it simply by using zIndex, not only it helped me capture child's onPress but also parent's onPress too, I was able to perform two different operations in a single component

Upvotes: 0

lloydaf
lloydaf

Reputation: 605

The behavior you described works as expected. This is because TouchableOpacity is a child component of TouchableWithoutFeedback, and so the click event propagates up the tree, triggering the click event of TouchableWithoutFeedback. To solve this issue, there is an event.stopPropagation() method you can call, which will stop the event from bubbling up.

Something like this should work.

onChildClick = (event)=>{ //do your logic here event.stopPropagation(); }

Upvotes: 1

Kamila Korzec
Kamila Korzec

Reputation: 99

With event.stopPropagation you can stop event from propagating up to the parents: https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation

First argument passed onClick is the event itself:

function onChildClick(e) {
    e.stopPropagation();
    console.log('The link was clicked.');
}

Upvotes: 4

Related Questions