Skip to content

Instantly share code, notes, and snippets.

@xiaody
Created June 8, 2018 05:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xiaody/206c4168f9001671c0a374af4558f582 to your computer and use it in GitHub Desktop.
Save xiaody/206c4168f9001671c0a374af4558f582 to your computer and use it in GitHub Desktop.
For any React.js user looking for a workaround to force non-passive touchmove listeners on iOS 11.3+, here is a component snippet that I'm using.
/*
* For nasty iOS Safari.
* Since iOS Safari 11.3+, all touchmove listeners are passive by default.
* Yet it doesn't fully support CSS touch-action like Chrome does.
* So here is a component to workaround.
*
* What is more weird is that **sometimes** even a non-passive listener cannot
* preventDefault. You have to nest this component inside another instance
* of it like:
* <NonPassiveTouchTarget>
* <NonPassiveTouchTarget onTouchMove={fnYourListener} />
* </NonPassiveTouchTarget>
*/
import React from 'react'
const OPTIONS = {passive: false}
class NonPassiveTouchTarget extends React.Component {
componentDidMount () {
this.node.addEventListener('touchmove', this.props.onTouchMove, OPTIONS)
}
componentDidUpdate (prevProps) {
if (prevProps.onTouchMove !== this.props.onTouchMove) {
this.node.removeEventListener('touchmove', prevProps.onTouchMove, OPTIONS)
this.node.addEventListener('touchmove', this.props.onTouchMove, OPTIONS)
}
}
componentWillUnmount () {
this.node.removeEventListener('touchmove', this.props.onTouchMove, OPTIONS)
}
ref = (node) => {
this.node = node
}
render () {
const {component: Component, onTouchMove, ...rest} = this.props
return (
<Component
ref={this.ref}
{...rest}
/>
)
}
}
NonPassiveTouchTarget.defaultProps = {
component: 'div',
onTouchMove () {}
}
export default NonPassiveTouchTarget
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment