Description
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.
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:
// ...
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.