Do you want to request a feature or report a bug?
Bug
What is the current behavior?
Calling e.preventDefault() on a synthetic onTouchStart event fails to prevent the click event. I also tried e.nativeEvent.preventDefault(), but this didn't make any difference.
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar (template: https://jsfiddle.net/84v837e9/).
Here's a div which is supposed to handle a hover case but not process a click the first time is is tapped via touch (click on desktop is fine). However tapping with touch (on a mobile device or using dev tools touch emulation) will trigger both touchstart and click immediately.
jsfiddle
const style = {
background: 'red',
width: 100,
height: 100,
// to ensure `touchstart` `preventDefault()` is allowed on mobile
touchAction: 'none'
};
class SomeButton extends React.Component {
constructor (props) {
super(props);
this.state = {
hover: false,
click: false
};
}
render () {
return (
<div
style={style}
onMouseEnter={() => this.setState({ hover: true })}
onClick={() => this.setState({ click: true })}
onTouchStart={e => {
if (!this.state.hover) {
e.preventDefault(); // doesn't work!
this.setState({ hover: true });
}
}}
>
{this.state.hover && 'hover!'}
{this.state.click && 'click!'}
</div>
);
}
}
However if I move the touchstart listener to componentDidMount and use the normal DOM API, everything works:
jsfiddle
// ...
class SomeButton extends React.Component {
constructor (props) {
// ...
}
componentDidMount () {
this.elem.addEventListener('touchstart', e => {
if (!this.state.hover) {
e.preventDefault(); // WORKS!
this.setState({ hover: true });
}
});
}
render () {
return (
<div
ref={elem => this.elem = elem}
{ /* ... (removed onTouchStart) ... */}
>
{/* ... */}
</div>
);
}
}
What is the expected behavior?
The first time a touchstart is processed, we only treat it as a hover, and wait to process the click event until after the next touchstart. If the pointer is a mouse, both events can be processed at once.
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
React 15.5.4. Not sure about previous React versions. Chrome for Android, Chrome for Mac emulating touch, Firefox for Mac emulating touch.
Do you want to request a feature or report a bug?
Bug
What is the current behavior?
Calling
e.preventDefault()on a syntheticonTouchStartevent fails to prevent theclickevent. I also triede.nativeEvent.preventDefault(), but this didn't make any difference.If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar (template: https://jsfiddle.net/84v837e9/).
Here's a div which is supposed to handle a hover case but not process a click the first time is is tapped via touch (click on desktop is fine). However tapping with touch (on a mobile device or using dev tools touch emulation) will trigger both
touchstartandclickimmediately.jsfiddle
However if I move the
touchstartlistener tocomponentDidMountand use the normal DOM API, everything works:jsfiddle
What is the expected behavior?
The first time a
touchstartis processed, we only treat it as a hover, and wait to process theclickevent until after the nexttouchstart. If the pointer is a mouse, both events can be processed at once.Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
React 15.5.4. Not sure about previous React versions. Chrome for Android, Chrome for Mac emulating touch, Firefox for Mac emulating touch.