React Native detect tap on View - react-native

I’m writing a React Native app and I want to detect tap/clicks anywhere on the screen so I put an onClick handler on my <View> element but it doesn’t seem to be working. Here is my render function:
<View style={styles.container} onClick={this.onClick}>
<Text style={styles.welcome}>
Tap to change the background
</Text>
</View>
What do I need to do?

For making any element to handle touch/click events in a React-Native UI, you need to put the element inside a TouchableOpacity, TouchableWithoutFeedback, TouchableNativeFeedback or TouchableHighlight element:
<TouchableHighlight onPress = { this.onClick }>
<View style={styles.container}>
<Text style={styles.welcome}>
Tap to change the background
</Text>
</View>
</TouchableHighlight>
Hope that helps.

In React Native version > 55.3 you make check onPress events into your View if use onStartShouldSetResponder props.
Like example:
<View
style={{ flex: 1 }}
onStartShouldSetResponder={() => console.log('You click by View')}
>
<ScrollView
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this.onRefresh} />
}
>
<Text>Awesome</Text>
</ScrollView>
</View>
In example I showed how you can get onPress event on View and not blocking other event behind them. Refresh control still work correct.

In my case the following works fine. You can use onTouchStart and onTouchEnd handlers on any View via props, for example:
<View onTouchStart={() => this.doSomething()} />
More information

This worked for me...
onTouchEnd={() => alert('TAPPED')}

The easiest way to do that:
<TouchableOpacity style={styles.container} onPress={()=> whateverFunc(parameter)}>
<Text style={styles.welcome}>
Tap to change the background
</Text>
</TouchableOpacity>
So, you need to replace the 'View' component to a 'TouchableOpacity' or any other Touchable component and you also need to replace the 'onClick' prop to 'onPress'. That's all. The wrapping of a view with a TouchableWhatever component is not necessary at all.

Related

Why does TouchableOpacity automatically trigger onPress in ReactNative Expo Snack?

I have a small ReactNative app in Expo Snack that includes a single components with a TouchableOpacity.
export default function AssetExample() {
function clicked() {
alert('clicked')
}
return (
<View style={styles.container}>
<TouchableOpacity onPress={clicked()}>
<Text style={styles.paragraph}>
Click the icon
</Text>
<Image style={styles.logo} source={require('../assets/snack-icon.png')} />
</TouchableOpacity>
</View>
);
}
Every time the app is started the alert is shown, meaning TouchableOpacity triggers onPress. Why? And how can I circumvent this?
You should pass the reference of your function to TouchableOpacity like this
<TouchableOpacity onPress={clicked}>
</TouchableOpacity>
or pass it with arrow function
<TouchableOpacity onPress={()=> clicked()}>
</TouchableOpacity>
so it will be called inside TouchableOpacity component whenever required (button click), otherwise it will be called only one time during render phase.
See these docs for handling events in React https://reactjs.org/docs/handling-events.html

TouchableHighlight not working although using the source code from official react native documentation

I'm a new react native developer and I have an issue with TouchableHighlight where it always shows an error "Error: React.Children.only expected to receive a single React element child." in addition while I remove it is work as usual and I assume if this issue come from my device/vscode/browser. Because I already follow the source code from https://reactnative.dev/docs/touchablehighlight but still show that error.
Error image
Image without TouchableHighlight tag
Here my code
render() {
return (
<View style={styles.container}>
<TouchableHighlight onPress={this.onPress}>
<View style={styles.button}>
<Text>Touch Here</Text>
</View>
</TouchableHighlight>
<View style={[styles.countContainer]}>
<Text style={[styles.countText]}>
{this.state.count ? this.state.count : null}
</Text>
</View>
</View>
);}
From the error message, the issue might happen if you pass Mutlipe child components to TouchableHighlight
From the docs:
TouchableHighlight must have one child (not zero or more than one). If you wish to have several child components, wrap them in a View
<TouchableHighlight onPress={onPress}>
<View style={styles.button}> // Mutlipe child components are wrapped in a View
<Text>Touch</Text> // component 1
<Text>Here</Text> // component 2
</View>
</TouchableHighlight>

React native Model popup style Issue

I make check box list on Model Pop up by using react native multiple select
checkbox list listed but it take full screen height
i am not able to fix this issue
please Any body help me
Outer Element would be a modal, then make a view of a specific height inside that modal,
Example
<Modal transparent={true}
visible={this.state.showDialog}
animationType='fade'>
<View style={{opacity:.5, backgroundColor:'black',flex:1}}/>
<View
style={{position:'absolute',padding:16,top:0,bottom:0,left:0,right:0
,justifyContent:'center',alignContent:"center",
alignItems:'center'}}>
<View style={{backgroundColor:’red’,padding:16,borderRadius:5,
width:'60%',height:'10%',alignContent:'center',alignItems:'center',justifyContent:'center'}}>
<Text style={{fontSize:14,alignSelf:'center',textAlign:'center'}}>
Sorry!!
</Text>
<Text style={{marginTop:5,fontSize:12,alignSelf:'center',textAlign:'center',color:’black’}}>
{this.props.errorMessage}
</Text>
<Button title='close'
onPress={()=>this.setState({showDialog:false})}/>
</View>
</View>
</Modal>

React Native onLongPress triggered onPress if pressed component is re-rendered

I am implementing an image gallery. There's a list of squared images, if user longPress an image component it will re-render to a selected image component which show a blur background and a tick on top of the image.
Here's the normal image component:
<TouchableOpacity
key={index}
onPress={this.normalModeImgClick(img, index)}
onLongPress={this.startSelectMode(index)}
>
<Image style={styles.img} source={{uri: img.resized_xs_url}}/>
</TouchableOpacity>
Here's the component at select mode:
<TouchableOpacity
key={itemIndex}
style={styles.selectedImgWrapper}
onPress={this.selectModeImgClick(imgItem, itemIndex)}
>
<Image style={styles.img} source={{uri: imgItem.img.resized_xs_url}}/>
{imgItem.selected &&
<View style={styles.selectedImgCover}>
<Image style={styles.selectedIcon} source={require('../../assets/icon_tick.png')}/>
</View>
}
</TouchableOpacity>
As you can see, if you longPress a normal image component startSelectMode will trigger, and that image will re-render and turned to a select mode component. However, selectModeImgClick will also be triggered which it is not supposed to (as the user is still doing the longPress action).
How to prevent this happening?
Accidentally discovered an alternative right after I posted the question, solved by adding an empty onLongPress function props to the selected mode component like this:
<TouchableOpacity
key={itemIndex}
style={styles.selectedImgWrapper}
onPress={this.selectModeImgClick(imgItem, itemIndex)}
// Override 'onLongPress' with an empty function
onLongPress={() => {}}
>
<Image style={styles.img} source={{uri: imgItem.img.resized_xs_url}}/>
{imgItem.selected &&
<View style={styles.selectedImgCover}>
<Image style={styles.selectedIcon} source={require('../../assets/icon_tick.png')}/>
</View>
}
</TouchableOpacity>
Since the component is not designed to have a longPress action, I'm looking forward to better solutions:

React Native: View onPress does not work

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
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>
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>
Alternatively you can also provide onStartShouldSetResponder to your view, like so:
<View onStartShouldSetResponder={() => console.log("View click")}>
// some code here
</View>
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>
onPress doesn't work on <View> tag use <TouchableOpacity> instead of View
<View>
<TouchableOpacity onPress={() => 'call your function here'}>
</TouchableOpacity>
</View>
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>
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
A new pressable component is provided in 0.67 of react native, which can solve your problem. It runs anywhere
enter image description here
well we can make the View have a onPress props onStartShouldSetResponder and onResponderGrant
<View
onStartShouldSetResponder={() => true}
onResponderGrant={() => console.log("view pressed")}
>
</View>
You can use TouchableOpacity for that purpose
<TouchableOpacity onPress={() => {your code here}}>
//Your inner views here
</TouchableOpacity>
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
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
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>