[fix] ScrollView passive event listener warning

'touchstart' and 'touchmove' listeners added to the document will
default to 'passive:true' (so that calls to 'preventDefault' will be
ignored). Source https://www.chromestatus.com/features/5093566007214080

To support 'scrollEnabled', listeners are bound to the underlying
ScrollView DOM node to avoid being passive.

Fix #477
This commit is contained in:
Nicolas Gallagher
2017-06-11 14:09:59 -07:00
parent b1b70a420d
commit 6ae68e948f

View File

@@ -7,6 +7,7 @@
*/
import debounce from 'debounce';
import findNodeHandle from '../../modules/findNodeHandle';
import View from '../View';
import ViewPropTypes from '../View/ViewPropTypes';
import React, { Component } from 'react';
@@ -69,8 +70,21 @@ export default class ScrollViewBase extends Component {
_debouncedOnScrollEnd = debounce(this._handleScrollEnd, 100);
_state = { isScrolling: false, scrollLastTick: 0 };
_node = null;
_handlePreventableScrollEvent = (handler: Function) => {
componentDidMount() {
this._node && this._node.addEventListener('scroll', this._handleScroll);
this._node && this._node.addEventListener('touchmove', this._handlePreventableTouchMove);
this._node && this._node.addEventListener('wheel', this._handlePreventableWheel);
}
componentWillUnmount() {
this._node && this._node.removeEventListener('scroll', this._handleScroll);
this._node && this._node.removeEventListener('touchmove', this._handlePreventableTouchMove);
this._node && this._node.removeEventListener('wheel', this._handlePreventableWheel);
}
_createPreventableScrollHandler = (handler: Function) => {
return (e: Object) => {
if (!this.props.scrollEnabled) {
e.preventDefault();
@@ -82,8 +96,15 @@ export default class ScrollViewBase extends Component {
};
};
_handleScroll = (e: SyntheticEvent) => {
e.persist();
_handlePreventableTouchMove = (e: Object) => {
this._createPreventableScrollHandler(this.props.onTouchMove)(e);
};
_handlePreventableWheel = (e: Object) => {
this._createPreventableScrollHandler(this.props.onWheel)(e);
};
_handleScroll = (e: Object) => {
e.stopPropagation();
const { scrollEventThrottle } = this.props;
// A scroll happened, so the scroll bumps the debounce.
@@ -120,6 +141,10 @@ export default class ScrollViewBase extends Component {
}
}
_setNodeRef = (element:View) => {
this._node = findNodeHandle(element);
};
_shouldEmitScrollEvent(lastTick: number, eventThrottle: number) {
const timeSinceLastTick = Date.now() - lastTick;
return eventThrottle > 0 && timeSinceLastTick >= eventThrottle;
@@ -130,8 +155,11 @@ export default class ScrollViewBase extends Component {
/* eslint-disable */
onMomentumScrollBegin,
onMomentumScrollEnd,
onScroll,
onScrollBeginDrag,
onScrollEndDrag,
onTouchMove,
onWheel,
removeClippedSubviews,
scrollEnabled,
scrollEventThrottle,
@@ -141,13 +169,6 @@ export default class ScrollViewBase extends Component {
...other
} = this.props;
return (
<View
{...other}
onScroll={this._handleScroll}
onTouchMove={this._handlePreventableScrollEvent(this.props.onTouchMove)}
onWheel={this._handlePreventableScrollEvent(this.props.onWheel)}
/>
);
return <View {...other} ref={this._setNodeRef} />;
}
}