2

So, I have a problem. I want to respond to a user pressing the mouse button (on desktop) or touching a div (on mobile). I'm trying to be compatile with evergreen browsers. This is what I tried so far:

  • listen only to mouseDown event. This works on desktop but doesn't work in mobile if the user is dragging. I want the handler to be called as soon as the user touches the screen, no matter if they're moving their finger in the process.
  • listen only to touchStart event. This works on mobile and desktop, except for Edge and Safari desktop, which don't support touch events.
  • listen to both, then preventDefault. This causes a double handler call on Chrome mobile. It seems that touch events are passive to allow uninterrupted scrolling on mobile Chrome, so preventDefualt has no effect on them . What I get is a warning message saying "[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/5093566007214080" in the console, preventDefault is ignored and my event is called twice.

Obviously this can be solved by sniffing touch events, but the net is full of self-righteous rants on how one has to be device-agnostic and that it's dangerous to detect touch events before the user interacted.

So I guess that the question is: is there a way to do what I want to do without sniffing for touch events?

Below my sample React code:

function handler(e) {
    console.log('handler called')
    e.preventDefault()
}

export default function MyElement() {
    return (
        <div
            onMouseDown={handler}
            onTouchStart={handler}
        >
        Hello
        </div>
    )
}
janesconference
  • 6,333
  • 8
  • 55
  • 73

1 Answers1

1

It turn out it's not yet possible in React. One workaround is set a flag the first time touchStart it's received.

touchHandler = () => {
  this.useTouch = true
  this.realHandler()
}

mouseHandler = () => {
  if (this.useTouch) return
  this.realHandler()
}

With the caveat that the first touchStart can be lost in case of dragging.

Quite disappointing.

janesconference
  • 6,333
  • 8
  • 55
  • 73