162

I'm facing a weird problem. In my react native app, if I set onPress event to View it is not triggered but if I set the same to Text inside View, it fires. What am I missing here?

<View style={{backgroundColor: "red", padding: 20}}>
  <Text onPress={()=> {
    console.log('works');
    }
  }>X</Text>
</View>


<View style={{backgroundColor: "red", padding: 20}} onPress={()=> {
    console.log('does not work');
    }
  }>
  <Text>X</Text>
</View>

Why is this so? Is this an issue with React Native? I'm using version 0.43

14 Answers 14

273

You can use TouchableOpacity for onPress event. View doesn't provide onPress prop.

<TouchableOpacity style={{backgroundColor: "red", padding: 20}} onPress={()=> {
    console.log('does not work');
    }
  }>
  <Text>X</Text>
</TouchableOpacity>
Sign up to request clarification or add additional context in comments.

2 Comments

Complete reference documentation is here: facebook.github.io/react-native/docs/touchableopacity.html
Can onPress work with an async function as its callback? I don't see mention of this in the official documentation.
39

You can wrap the view with a TouchableWithoutFeedback and then use onPress and friends like usual. Also you can still block pointerEvents by setting the attribute on on the child view, it even blocks pointer events on the parent TouchableWithoutFeedback, its interesting, this was my need on Android, I didn't test on iOS:

https://facebook.github.io/react-native/docs/touchablewithoutfeedback.html

<TouchableWithoutFeedback onPressIn={this.closeDrawer}>
    <Animated.View style={[styles.drawerBackground, styleBackground]} pointerEvents={isOpen ? undefined : 'none'} />
</TouchableWithoutFeedback>

2 Comments

Tested on iOS and it works just fine. Both with touchable without feedback and touchable highlight
Thanks for sharing @habed! Did the pointerEventsNone on the child block presses on the wrapping parent?
15

Alternatively you can also provide onStartShouldSetResponder to your view, like so:

<View onStartShouldSetResponder={() => console.log("View click")}>
  // some code here
</View>

1 Comment

Although this works, it should be kept in mind that, in case you have a ScrollView containing 1 or more View that use onStartShouldSetResponder, the event attached to each View will be dispatched on the spot and you will not be able to scroll. This is hard to notice if you are using an iOS simulator on a Mac, but you will see it when the app is deployed and running on the phone. this is the correct answer
7

You can use TouchableOpacity, TouchableHighlight, TouchableNativeFeedback, to achieve this. View component doesn't provide onPress as props. So you use these instead of that.

<TouchableNativeFeedback
        onPress={this._onPressButton}
</TouchableNativeFeedback>

OR

<TouchableHighlight onPress={this._onPressButton}>
</TouchableHighlight>

OR

<TouchableOpacity onPress={this._onPressButton}>
</TouchableOpacity>

Comments

6

For this issue you can make use either

touchable(opacity,withoutfeedback,....)

or Pressable component which is currently available in react native Package like,

<TouchableOpacity onPress={()=>console.log("Pressed")}>
  ....
</TouchableOpacity>

or

<Pressable onPress={()=>console.log("Pressed")}>
  ....
</Pressable> 

Comments

5

onPress doesn't work on <View> tag use <TouchableOpacity> instead of View

<View>
<TouchableOpacity onPress={() => 'call your function here'}>
</TouchableOpacity>
</View>

Comments

3

2021

If you're looking for a more extensive and future-proof way to handle touch-based input, check out the Pressable API.

Source: https://reactnative.dev/docs/touchablewithoutfeedback

Comments

2

A new pressable component is provided in 0.67 of react native, which can solve your problem. It runs anywhere enter image description here

Comments

1

well we can make the View have a onPress props onStartShouldSetResponder and onResponderGrant

<View
    onStartShouldSetResponder={() => true}
    onResponderGrant={() => console.log("view pressed")}
  >
</View>

Comments

1

You can use TouchableOpacity for that purpose

<TouchableOpacity onPress={() => {your code here}}>
    //Your inner views here
</TouchableOpacity>

Comments

1

In View onPress will not work because onPress event is not supported in view tag.That is why it is not working but you can go to this link https://reactnative.dev/docs/view

Comments

1

You could use 'onTouchEnd' event handler which is similar to 'onPress' as onPress prop is unavailable on the 'View' component.

<View onTouchEnd={()=>{alert("Hello")}>

Comments

0

For anybody who's lookig for a solution to this, as of RN 0.63, there is a new Pressabe api. It might have rolled out a couple versions earlier but it works great for such use cases.

<Pressable onPress={onPressFunction}>
    <Text onPress={() => {
        console.log('works');
    }}>X</Text>
</Pressable>

2 Comments

That didn't work with me
Thanks, this is just what I needed, because it not only registers presses on the current element but also on all of its children! :)
0

You can use Pressable components which is react native core component and wrap your View or any other component in Pressable which don't have onPress prop.

Like this:

<Pressable onPress={()=>console.log('pressed')}>
   <View>
     <Text>Some Text</Text>
   </View>
</Pressable>

Pressable Documentation

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.