[fix] support React Native props in 'setNativeProps'

React Native allows props like 'pointerEvents' to be set using
'setNativeProps'.

Fix #392
This commit is contained in:
Nicolas Gallagher
2017-03-20 22:29:32 -07:00
parent e05e2122d7
commit 68068f8cb6
3 changed files with 81 additions and 51 deletions
+4 -4
View File
@@ -6,6 +6,7 @@
* @flow
*/
import createDOMProps from '../createDOMProps';
import findNodeHandle from '../findNodeHandle';
import StyleRegistry from '../../apis/StyleSheet/registry';
import UIManager from '../../apis/UIManager';
@@ -70,10 +71,9 @@ const NativeMethodsMixin = {
const node = findNodeHandle(this);
const classList = [...node.classList];
const { className, style } = StyleRegistry.resolveStateful(nativeProps.style, classList);
const props = { ...nativeProps, className, style };
UIManager.updateView(node, props, this);
const domProps = createDOMProps(nativeProps, style =>
StyleRegistry.resolveStateful(style, classList));
UIManager.updateView(node, domProps, this);
}
};
+2 -47
View File
@@ -1,5 +1,6 @@
import '../injectResponderEventPlugin';
import createDOMProps from '../createDOMProps';
import getAccessibilityRole from '../getAccessibilityRole';
import normalizeNativeEvent from '../normalizeNativeEvent';
import React from 'react';
@@ -52,28 +53,12 @@ const wrapEventHandler = handler => e => {
};
const createDOMElement = (component, rnProps) => {
const {
accessibilityLabel,
accessibilityLiveRegion,
accessible = true,
style: rnStyle,
testID,
type,
/* eslint-disable */
accessibilityComponentType,
accessibilityRole,
accessibilityTraits,
/* eslint-enable */
...domProps
} = rnProps || emptyObject;
// use equivalent platform elements where possible
const role = getAccessibilityRole(rnProps || emptyObject);
const accessibilityComponent = role && roleComponents[role];
const Component = accessibilityComponent || component;
// convert React Native styles to DOM styles
const { className, style } = StyleRegistry.resolve(rnStyle) || emptyObject;
const domProps = createDOMProps(rnProps, style => StyleRegistry.resolve(style));
// normalize DOM events to match React Native events
// TODO: move this out of the render path
@@ -86,36 +71,6 @@ const createDOMElement = (component, rnProps) => {
}
}
if (!accessible) {
domProps['aria-hidden'] = true;
}
if (accessibilityLabel) {
domProps['aria-label'] = accessibilityLabel;
}
if (accessibilityLiveRegion) {
domProps['aria-live'] = accessibilityLiveRegion;
}
if (className && className !== '') {
domProps.className = domProps.className ? `${domProps.className} ${className}` : className;
}
if (role) {
domProps.role = role;
if (role === 'button') {
domProps.type = 'button';
} else if (role === 'link' && domProps.target === '_blank') {
domProps.rel = `${domProps.rel || ''} noopener noreferrer`;
}
}
if (style) {
domProps.style = style;
}
if (testID) {
domProps['data-testid'] = testID;
}
if (type) {
domProps.type = type;
}
return <Component {...domProps} />;
};
+75
View File
@@ -0,0 +1,75 @@
import getAccessibilityRole from '../getAccessibilityRole';
import StyleSheet from '../../apis/StyleSheet';
const emptyObject = {};
const pointerEventStyles = StyleSheet.create({
auto: {
pointerEvents: 'auto'
},
'box-none': {
pointerEvents: 'box-none'
},
'box-only': {
pointerEvents: 'box-only'
},
none: {
pointerEvents: 'none'
}
});
const createDOMProps = (rnProps, resolveStyle) => {
const {
accessibilityLabel,
accessibilityLiveRegion,
accessible = true,
pointerEvents,
style: rnStyle,
testID,
type,
/* eslint-disable */
accessibilityComponentType,
accessibilityRole,
accessibilityTraits,
/* eslint-enable */
...domProps
} = rnProps || emptyObject;
const pointerEventStyle = pointerEvents && pointerEventStyles[pointerEvents];
const { className, style } = resolveStyle([rnStyle, pointerEventStyle]) || emptyObject;
const role = getAccessibilityRole(rnProps || emptyObject);
if (!accessible) {
domProps['aria-hidden'] = true;
}
if (accessibilityLabel) {
domProps['aria-label'] = accessibilityLabel;
}
if (accessibilityLiveRegion) {
domProps['aria-live'] = accessibilityLiveRegion;
}
if (className && className !== '') {
domProps.className = domProps.className ? `${domProps.className} ${className}` : className;
}
if (role) {
domProps.role = role;
if (role === 'button') {
domProps.type = 'button';
} else if (role === 'link' && domProps.target === '_blank') {
domProps.rel = `${domProps.rel || ''} noopener noreferrer`;
}
}
if (style) {
domProps.style = style;
}
if (testID) {
domProps['data-testid'] = testID;
}
if (type) {
domProps.type = type;
}
return domProps;
};
module.exports = createDOMProps;