From ad883486db84534c0a84d941d5cb58afcaa6dc6e Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Wed, 23 May 2018 16:47:08 -0700 Subject: [PATCH] [change] whitelist props passed to React DOM Avoiding unknown property warnings from React DOM. Many components within and build upon React Native do not filter their own properties and spread them into View. It is expected that React Native ignore these properties. Fix #898 --- .../src/exports/View/filterSupportedProps.js | 75 +++++++++++++++++++ .../src/exports/View/index.js | 25 ++----- 2 files changed, 81 insertions(+), 19 deletions(-) create mode 100644 packages/react-native-web/src/exports/View/filterSupportedProps.js diff --git a/packages/react-native-web/src/exports/View/filterSupportedProps.js b/packages/react-native-web/src/exports/View/filterSupportedProps.js new file mode 100644 index 0000000000..7ed9e59243 --- /dev/null +++ b/packages/react-native-web/src/exports/View/filterSupportedProps.js @@ -0,0 +1,75 @@ +const whitelist = { + accessibilityComponentType: true, + accessibilityLabel: true, + accessibilityLiveRegion: true, + accessibilityRole: true, + accessibilityTraits: true, + accessible: true, + children: true, + disabled: true, + importantForAccessibility: true, + onBlur: true, + onContextMenu: true, + onFocus: true, + onMoveShouldSetResponder: true, + onMoveShouldSetResponderCapture: true, + onResponderEnd: true, + onResponderGrant: true, + onResponderMove: true, + onResponderReject: true, + onResponderRelease: true, + onResponderStart: true, + onResponderTerminate: true, + onResponderTerminationRequest: true, + onScrollShouldSetResponder: true, + onScrollShouldSetResponderCapture: true, + onSelectionChangeShouldSetResponder: true, + onSelectionChangeShouldSetResponderCapture: true, + onStartShouldSetResponder: true, + onStartShouldSetResponderCapture: true, + onTouchCancel: true, + onTouchCancelCapture: true, + onTouchEnd: true, + onTouchEndCapture: true, + onTouchMove: true, + onTouchMoveCapture: true, + onTouchStart: true, + onTouchStartCapture: true, + pointerEvents: true, + style: true, + testID: true, + // escape-hatches for ScrollView + onScroll: true, + onWheel: true, + // escape-hatches for Touchable keyboard support + onKeyDown: true, + onKeyPress: true, + onKeyUp: true, + // escape-hatches for creating hover effects + onMouseEnter: true, + onMouseLeave: true, + onMouseMove: true, + onMouseOver: true, + onMouseOut: true, + // unstable escape-hatches for web + className: true, + href: true, + onClick: true, + onClickCapture: true, + rel: true, + target: true +}; + +const filterSupportedProps = props => { + const safeProps = {}; + for (const prop in props) { + if (props.hasOwnProperty(prop)) { + if (whitelist[prop] || prop.indexOf('aria-') === 0 || prop.indexOf('data-') === 0) { + safeProps[prop] = props[prop]; + } + } + } + return safeProps; +}; + +export default filterSupportedProps; diff --git a/packages/react-native-web/src/exports/View/index.js b/packages/react-native-web/src/exports/View/index.js index 12184f1ddd..2407c1fc33 100644 --- a/packages/react-native-web/src/exports/View/index.js +++ b/packages/react-native-web/src/exports/View/index.js @@ -10,6 +10,7 @@ import applyLayout from '../../modules/applyLayout'; import applyNativeMethods from '../../modules/applyNativeMethods'; import { bool } from 'prop-types'; import createElement from '../createElement'; +import filterSupportedProps from './filterSupportedProps'; import invariant from 'fbjs/lib/invariant'; import StyleSheet from '../StyleSheet'; import ViewPropTypes, { type ViewProps } from './ViewPropTypes'; @@ -36,22 +37,8 @@ class View extends Component { static propTypes = ViewPropTypes; render() { - const { - hitSlop, - /* eslint-disable */ - accessibilityViewIsModal, - collapsable, - needsOffscreenAlphaCompositing, - onAccessibilityTap, - onLayout, - onMagicTap, - removeClippedSubviews, - renderToHardwareTextureAndroid, - shouldRasterizeIOS, - tvParallaxProperties, - /* eslint-enable */ - ...otherProps - } = this.props; + const hitSlop = this.props.hitSlop; + const supportedProps = filterSupportedProps(this.props); if (process.env.NODE_ENV !== 'production') { React.Children.toArray(this.props.children).forEach(item => { @@ -64,7 +51,7 @@ class View extends Component { const { isInAParentText } = this.context; - otherProps.style = StyleSheet.compose( + supportedProps.style = StyleSheet.compose( styles.initial, StyleSheet.compose(isInAParentText && styles.inline, this.props.style) ); @@ -72,10 +59,10 @@ class View extends Component { if (hitSlop) { const hitSlopStyle = calculateHitSlopStyle(hitSlop); const hitSlopChild = createElement('span', { style: [styles.hitSlop, hitSlopStyle] }); - otherProps.children = React.Children.toArray([hitSlopChild, otherProps.children]); + supportedProps.children = React.Children.toArray([hitSlopChild, supportedProps.children]); } - return createElement('div', otherProps); + return createElement('div', supportedProps); } }