react: Chrome 56 breaks touch events

Do you want to request a feature or report a bug? Bug

What is the current behavior? React attaches events to the document node which causes the latest version of Chrome to issue the following warning.

Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/5093566007214080

It appears that Chrome now treats all document level touch events as passive.

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/reactjs/69z2wepo/).

class App extends Component {
  render() {
    return (
      <div
          className="box"
          onTouchStart={e=>{e.preventDefault()}}
          onTouchMove={e=>{e.preventDefault()}}
      >
          Drag Me
      </div>
    );
  }
}

What is the expected behavior? preventDefault should be allowed, which means React should pass { passive: false } when adding event listeners.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React? React 15.4.1, Chrome 56.0.2924.87, Windows 10

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 45
  • Comments: 17 (2 by maintainers)

Commits related to this issue

Most upvoted comments

Ok. This will be interesting to deal with. If Chrome makes a breaking change, does that mean libraries should respond by unbreaking it? Effectively undoing the purpose.

Now this whole thing will be complicated further by the fact that React Fiber is a whole shift to be able to write 60fps apps with active event listeners. In that world defaulting to active makes more sense.

On the flip side we’re not quite there yet in the ecosystem and there is some action from apps to be able to make that palatable.

This will need some careful consideration to make the right choices for defaults.

@oliviertassinari Manually attaching listeners seems wrong. I think this should be fixed in React.

No, it wasn’t.

Rather than set passive:false, it’s much better to apply the appropriate touch-action to disable scrolling where desired. See here.

I would link that issue with #6436.

@mstijak If you are looking for a workaround. You can manually use the addEventListener and removeEventListener DOM API with the right option.

Yes, we’ve accidentally “fixed” this with that change in one of the RCs, but in the 17 we’re explicily making onWheel, onTouchStart, and onTouchMove passive to align with the browser behavior. Since this change has improved the scrolling performance on the web overall, we don’t think it would be productive to “undo” the fix — as it’s still likely going to lead to performance problems. For now, you can keep using refs + addEventListener as a workaround if you need active event listeners.

@mstijak mouse and touch are orthogonal here. You can/should still call preventDefault, just also set touch-action to indicate declaratively what touch gestures you want disabled.

@sebmarkbage it can, in at least the same scenarios you can disable scrolling via TouchEvent.preventDefault in Safari. I.e. once scrolling has started you can’t change it. You may want to set pan-up when at the bottom.