Replace passive addEventListener to onTouchStart method

Aleksandra picture Aleksandra · Apr 29, 2019 · Viewed 7.9k times · Source

I want to replace document.addEventListener('touchstart', handler, {passive: true}); to onTouchStart={handler}

So if I had passive flag on true then my handle method should like:

const handler = (event) => { 
    console.log(event); 
} 

and when I have a flag on false:

 const handler = (event) => { 
    event.preventDefault();
    console.log(event); 
} 

I'm talking about Passive Event Listeners and browser behavior. Is it only about using preventDefault() or not ? Do I understand it correctly or not ?

Answer

Vencovsky picture Vencovsky · Apr 29, 2019

Looking at the docs here

Currently, browsers can't know if a touch event listener is going to cancel the scroll, so they always wait for the listener to finish before scrolling the page. Passive event listeners solve this problem by enabling you to set a flag in the options parameter of addEventListener indicating that the listener will never cancel the scroll.

This means that you change the behavior of the event. If you only change the preventDefault, it still have the normal behavior of the event (not passive). So this doesn't change anything.

The reason why in the docs they say to "remove" the preventDefault is that you need the default action of the event when setting passive to true.

This will be the normal event, without passive.

onTouchStart={handler}

This will add the passive action, but remove because of preventDefault

const handler = (event) => { 
    event.preventDefault();
    console.log(event); 
} 
...
onTouchStart={handler}

So you need the .addEventListener with {passive: true} and also remove any call of .preventDefault().

Here is an example of how to do this in any component.

class SomeClass extends React.Component {

  componentDidMount() {
    this.elementYouWant.addEventListener("touchstart", this.handleTouchStart, {passive: true});
  }

  componentWillUnmount() {
    this.elementYouWant.removeEventListener("touchstart", this.handleTouchStart);
  }

  handleTouchStart = (e) => {
    console.log(e);
  }

  render() {
    return (
      <div ref={e => this.elementYouWant = e}>
        ...
      </div>
    );
  }

}

I searched on how to pass the option paramenter to the event listener without needing to create it in componentDidMount and componentWillUnmount in react, but coudn't find it.

You can see here the best way of implementing it because some browser will interpret {passive: true} as true and this will create a different behavior.