Compare commits

..

5 Commits

Author SHA1 Message Date
Nicolas Gallagher
ec2db3e2a3 0.0.78 2017-03-19 18:45:21 -07:00
Bruno Lemos
e6f00f7592 [add] default option for Platform.select
See: f30ab35e92
2017-03-19 15:27:07 -07:00
Nicolas Gallagher
976320916e [change] move bridge code into createDOMElement
Moves event normalization and the ResponderEventPlugin injection from
'View' to 'createDOMElement'.

The 'react-native-web/lite' variant is removed from the performance
directory as the implementation is not substantially different.
Micro-optimizations to marginally narrow the performance gap to
css-modules.
2017-03-19 15:19:26 -07:00
Nicolas Gallagher
808790505e [change] onLayout improvements
1. Fires when window resizes
2. Guards against nodes being unmounted

Fix #397
Ref #60
2017-03-19 13:29:47 -07:00
Nicolas Gallagher
89ad493ce5 Update benchmark results 2017-03-14 17:23:16 -07:00
17 changed files with 173 additions and 258 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "react-native-web",
"version": "0.0.77",
"version": "0.0.78",
"description": "React Native for Web",
"main": "dist/index.js",
"files": [
@@ -25,7 +25,6 @@
"dependencies": {
"animated": "^0.2.0",
"array-find-index": "^1.0.2",
"asap": "^2.0.5",
"babel-runtime": "^6.23.0",
"debounce": "^1.0.0",
"deep-assign": "^2.0.0",

View File

@@ -10,27 +10,18 @@ open ./performance/index.html
## Notes
The components used in the render benchmarks are simple enough to be
implemented by multiple styling libraries. The implementations are not
equivalent but are useful for framing the relative performance of
`react-native-web` against these tests.
The implementations are not equivalent. For example, the `react-native-web`
implementation of `View` does more than just styling. The
`react-native-web/lite` variant implements a minimal `View` that allows for a
more direct comparison with the `css-modules` baseline.
implemented by multiple UI or style libraries. The implementations are not
equivalent in functionality.
## Benchmark results
Typical render timings*: mean / two standard deviations
Typical render timings*: mean ± two standard deviations
Version: 0.0.73
| Implementation | Deep tree (ms) | Wide tree (ms) |
| Implementation | Deep tree (ms) | Wide tree (ms) |
| :--- | ---: | ---: |
| css-modules | `80.47` `±18.04` | `166.91` `±19.90` |
| react-native-web/lite | `87.91` 13.37` | `181.45` `±20.06` |
| react-native-web | `113.45` 09.27` | `237.33` 38.77` |
| styled-components | `170.86` 15.67` | `378.83` `±36.11` |
| glamor | `275.41` `±19.56` | `474.76` `±29.02` |
| `css-modules` | `76.66` `±18.46` | `157.03` `±19.79` |
| `react-native-web@0.0.78` | `90.13` 20.91` | `198.72` `±24.44` |
| `styled-components@2.0.0-7` | `263.06` 31.87` | `564.53` 27.62` |
| `glamor@3.0.0-1` | `267.49` 35.12` | `451.99` `±37.32` |
*MacBook Pro (13-inch, Early 2011); 2.7 GHz Intel Core i7; 16 GB 1600 MHz DDR3. Google Chrome 56.

View File

@@ -1,49 +0,0 @@
/* eslint-disable react/prop-types */
import React from 'react';
import StyleSheet from 'react-native/apis/StyleSheet';
import View from '../View/lite';
const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other }) => (
<View
{...other}
style={[
styles[`color${color}`],
fixed && styles.fixed,
layout === 'row' && styles.row,
outer && styles.outer
]}
/>
);
const styles = StyleSheet.create({
outer: {
padding: 4
},
row: {
flexDirection: 'row'
},
color0: {
backgroundColor: '#222'
},
color1: {
backgroundColor: '#666'
},
color2: {
backgroundColor: '#999'
},
color3: {
backgroundColor: 'blue'
},
color4: {
backgroundColor: 'orange'
},
color5: {
backgroundColor: 'red'
},
fixed: {
width: 20,
height: 20
}
});
module.exports = Box;

View File

@@ -1,32 +0,0 @@
import createDOMElement from 'react-native/modules/createDOMElement';
import StyleSheet from 'react-native/apis/StyleSheet';
const View = props => createDOMElement('div', { ...props, style: [styles.initial, props.style] });
const styles = StyleSheet.create({
initial: {
alignItems: 'stretch',
borderWidth: 0,
borderStyle: 'solid',
boxSizing: 'border-box',
display: 'flex',
flexBasis: 'auto',
flexDirection: 'column',
margin: 0,
padding: 0,
position: 'relative',
// button and anchor reset
backgroundColor: 'transparent',
color: 'inherit',
font: 'inherit',
textAlign: 'inherit',
textDecorationLine: 'none',
// list reset
listStyle: 'none',
// fix flexbox bugs
minHeight: 0,
minWidth: 0
}
});
module.exports = View;

View File

@@ -1,7 +0,0 @@
import Box from './Box/lite';
import View from './View/lite';
export default {
Box,
View
};

View File

@@ -1,7 +1,6 @@
import cssModules from './implementations/css-modules';
import glamor from './implementations/glamor';
import reactNative from './implementations/react-native-web';
import reactNativeLite from './implementations/react-native-web/lite';
import styledComponents from './implementations/styled-components';
import renderDeepTree from './tests/renderDeepTree';
@@ -10,13 +9,11 @@ import renderWideTree from './tests/renderWideTree';
const tests = [
// deep tree
() => renderDeepTree('css-modules', cssModules),
() => renderDeepTree('react-native-web/lite', reactNativeLite),
() => renderDeepTree('react-native-web', reactNative),
() => renderDeepTree('styled-components', styledComponents),
() => renderDeepTree('glamor', glamor),
// wide tree
() => renderWideTree('css-modules', cssModules),
() => renderWideTree('react-native-web/lite', reactNativeLite),
() => renderWideTree('react-native-web', reactNative),
() => renderWideTree('styled-components', styledComponents),
() => renderWideTree('glamor', glamor)

View File

@@ -3,9 +3,9 @@
"private": true,
"dependencies": {
"classnames": "^2.2.5",
"glamor": "^2.20.24",
"glamor": "3.0.0-1",
"marky": "^1.1.3",
"styled-components": "2.0.0-5"
"styled-components": "2.0.0-7"
},
"devDependencies": {
"css-loader": "^0.26.2",

View File

@@ -19,7 +19,9 @@ module.exports = {
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: { cacheDirectory: true }
query: {
cacheDirectory: true
}
}
]
},

View File

@@ -155,10 +155,6 @@ colormin@^1.0.5:
css-color-names "0.0.4"
has "^1.0.1"
colors@0.5.x:
version "0.5.1"
resolved "https://registry.yarnpkg.com/colors/-/colors-0.5.1.tgz#7d0023eaeb154e8ee9fce75dcb923d0ed1667774"
colors@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
@@ -171,15 +167,9 @@ core-js@^2.4.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
css-color-list@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/css-color-list/-/css-color-list-0.0.1.tgz#8718e8695ae7a2cc8787be8715f1c008a7f28b15"
dependencies:
css-color-names "0.0.1"
css-color-names@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.1.tgz#5d0548fa256456ede4a9a0c2ac7ab19d3eb1ad81"
css-color-keywords@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
css-color-names@0.0.4:
version "0.0.4"
@@ -218,13 +208,13 @@ css-selector-tokenizer@^0.7.0:
fastparse "^1.1.1"
regexpu-core "^1.0.0"
css-to-react-native@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-1.0.6.tgz#728c7e774e56536558a0ecaa990d9507c43a4ac4"
css-to-react-native@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-2.0.1.tgz#179b25cba8cab7798118b1679b81f4d6b3fa0de3"
dependencies:
css-color-list "0.0.1"
css-color-keywords "^1.0.0"
fbjs "^0.8.5"
nearley "^2.7.7"
postcss-value-parser "^3.3.0"
cssesc@^0.1.0:
version "0.1.0"
@@ -282,10 +272,6 @@ defined@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
discontinuous-range@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
electron-to-chromium@^1.2.3:
version "1.2.4"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.2.4.tgz#9751cbea89fa120bf88c226ba41eb8d0b6f1b597"
@@ -336,7 +322,15 @@ function-bind@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
glamor@^2.20.22, glamor@^2.20.24:
glamor@3.0.0-1:
version "3.0.0-1"
resolved "https://registry.yarnpkg.com/glamor/-/glamor-3.0.0-1.tgz#60f489e96d96c12620803d3677ac26413cb76a95"
dependencies:
babel-runtime "^6.18.0"
fbjs "^0.8.8"
object-assign "^4.1.0"
glamor@^2.20.22:
version "2.20.24"
resolved "https://registry.yarnpkg.com/glamor/-/glamor-2.20.24.tgz#a299af2eec687322634ba38e4a0854d8743d2041"
dependencies:
@@ -501,14 +495,6 @@ mkdirp@~0.5.1:
dependencies:
minimist "0.0.8"
nearley@^2.7.7:
version "2.7.13"
resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.7.13.tgz#ae19927cc821a4b517de91962db9ed0e90d991fa"
dependencies:
nomnom "~1.6.2"
railroad-diagrams "^1.0.0"
randexp "^0.4.2"
node-fetch@^1.0.1:
version "1.6.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04"
@@ -516,13 +502,6 @@ node-fetch@^1.0.1:
encoding "^0.1.11"
is-stream "^1.0.1"
nomnom@~1.6.2:
version "1.6.2"
resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.6.2.tgz#84a66a260174408fc5b77a18f888eccc44fb6971"
dependencies:
colors "0.5.x"
underscore "~1.4.4"
normalize-range@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
@@ -803,17 +782,6 @@ query-string@^4.1.0:
object-assign "^4.1.0"
strict-uri-encode "^1.0.0"
railroad-diagrams@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e"
randexp@^0.4.2:
version "0.4.4"
resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.4.tgz#ba68265f4a9f9e85f5814d34e160291f939f168e"
dependencies:
discontinuous-range "1.0.0"
ret "~0.1.10"
reduce-css-calc@^1.2.6:
version "1.3.0"
resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716"
@@ -854,10 +822,6 @@ regjsparser@^0.1.4:
dependencies:
jsesc "~0.5.0"
ret@~0.1.10:
version "0.1.13"
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.13.tgz#38c2702ece654978941edd8b7dfac6aeeef4067d"
sax@~1.2.1:
version "1.2.2"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.2.tgz#fd8631a23bc7826bef5d871bdb87378c95647828"
@@ -900,23 +864,23 @@ style-loader@^0.13.2:
dependencies:
loader-utils "^1.0.2"
styled-components@2.0.0-5:
version "2.0.0-5"
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-2.0.0-5.tgz#df802d110cfb1a08a37e7746ecff11c765075e34"
styled-components@2.0.0-7:
version "2.0.0-7"
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-2.0.0-7.tgz#a420b99622eacec26ae3d62c1c75985791d9691b"
dependencies:
buffer "^5.0.3"
css-to-react-native "^1.0.6"
css-to-react-native "2.0.1"
fbjs "^0.8.9"
glamor "^2.20.22"
inline-style-prefixer "^2.0.5"
is-function "^1.0.1"
is-plain-object "^2.0.1"
stylis "^1.1.13"
stylis "^1.2.0"
supports-color "^3.2.3"
stylis@^1.1.13:
version "1.1.13"
resolved "https://registry.yarnpkg.com/stylis/-/stylis-1.1.13.tgz#e15095d0027f49683f7556e31df184c1eafe1d6d"
stylis@^1.2.0:
version "1.2.6"
resolved "https://registry.yarnpkg.com/stylis/-/stylis-1.2.6.tgz#d7e72d3c8de52684a4f6cc82b3086e3634dc3c13"
supports-color@^2.0.0:
version "2.0.0"
@@ -944,10 +908,6 @@ ua-parser-js@^0.7.9:
version "0.7.12"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb"
underscore@~1.4.4:
version "1.4.4"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.4.4.tgz#61a6a32010622afa07963bf325203cf12239d604"
uniq@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"

View File

@@ -6,11 +6,11 @@
* @flow
*/
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
import debounce from 'debounce';
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
import invariant from 'fbjs/lib/invariant';
const win = ExecutionEnvironment.canUseDOM ? window : { screen: {} };
const win = canUseDOM ? window : { screen: {} };
const dimensions = {};
@@ -38,6 +38,9 @@ class Dimensions {
}
Dimensions.set();
ExecutionEnvironment.canUseDOM && window.addEventListener('resize', debounce(Dimensions.set, 50));
if (canUseDOM) {
window.addEventListener('resize', debounce(Dimensions.set, 16), false);
}
module.exports = Dimensions;

View File

@@ -1,6 +1,6 @@
const Platform = {
OS: 'web',
select: (obj: Object) => obj.web
select: (obj: Object) => 'web' in obj ? obj.web : obj.default
};
module.exports = Platform;

View File

@@ -1,7 +1,7 @@
import asap from 'asap';
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
import generateCss from './generateCss';
import hash from './hash';
import requestAnimationFrame from 'fbjs/lib/requestAnimationFrame';
import staticCss from './staticCss';
const emptyObject = {};
@@ -111,7 +111,7 @@ class StyleManager {
className = createClassName(prop, value);
this._addToCache(className, prop, value);
if (canUseDOM) {
asap(() => {
requestAnimationFrame(() => {
const sheet = this.mainSheet.sheet;
// avoid injecting if the rule already exists (e.g., server rendered, hot reload)
if (this.mainSheet.textContent.indexOf(className) === -1) {

View File

@@ -1,5 +1,5 @@
import asap from 'asap';
import CSSPropertyOperations from 'react-dom/lib/CSSPropertyOperations';
import requestAnimationFrame from 'fbjs/lib/requestAnimationFrame';
const getRect = node => {
const height = node.offsetHeight;
@@ -15,13 +15,15 @@ const getRect = node => {
};
const measureLayout = (node, relativeToNativeNode, callback) => {
asap(() => {
const relativeNode = relativeToNativeNode || node.parentNode;
const relativeRect = getRect(relativeNode);
const { height, left, top, width } = getRect(node);
const x = left - relativeRect.left;
const y = top - relativeRect.top;
callback(x, y, width, height, left, top);
requestAnimationFrame(() => {
const relativeNode = relativeToNativeNode || (node && node.parentNode);
if (node && relativeNode) {
const relativeRect = getRect(relativeNode);
const { height, left, top, width } = getRect(node);
const x = left - relativeRect.left;
const y = top - relativeRect.top;
callback(x, y, width, height, left, top);
}
});
};
@@ -43,13 +45,16 @@ const UIManager = {
},
measureInWindow(node, callback) {
const { height, left, top, width } = getRect(node);
callback(left, top, width, height);
requestAnimationFrame(() => {
if (node) {
const { height, left, top, width } = getRect(node);
callback(left, top, width, height);
}
});
},
measureLayout(node, relativeToNativeNode, onFail, onSuccess) {
const relativeTo = relativeToNativeNode || node.parentNode;
measureLayout(node, relativeTo, onSuccess);
measureLayout(node, relativeToNativeNode, onSuccess);
},
updateView(node, props, component /* only needed to surpress React errors in development */) {

View File

@@ -1,49 +1,11 @@
import '../../modules/injectResponderEventPlugin';
import applyLayout from '../../modules/applyLayout';
import applyNativeMethods from '../../modules/applyNativeMethods';
import createDOMElement from '../../modules/createDOMElement';
import normalizeNativeEvent from '../../modules/normalizeNativeEvent';
import StyleSheet from '../../apis/StyleSheet';
import ViewPropTypes from './ViewPropTypes';
import { Component, PropTypes } from 'react';
const eventHandlerNames = [
'onClick',
'onClickCapture',
'onMoveShouldSetResponder',
'onMoveShouldSetResponderCapture',
'onResponderGrant',
'onResponderMove',
'onResponderReject',
'onResponderRelease',
'onResponderTerminate',
'onResponderTerminationRequest',
'onStartShouldSetResponder',
'onStartShouldSetResponderCapture',
'onTouchCancel',
'onTouchCancelCapture',
'onTouchEnd',
'onTouchEndCapture',
'onTouchMove',
'onTouchMoveCapture',
'onTouchStart',
'onTouchStartCapture'
];
const _normalizeEventForHandler = handler => e => {
e.nativeEvent = normalizeNativeEvent(e.nativeEvent);
return handler(e);
};
const normalizeEventHandlers = props => {
eventHandlerNames.forEach(handlerName => {
const handler = props[handlerName];
if (typeof handler === 'function') {
props[handlerName] = _normalizeEventForHandler(handler);
}
});
};
const emptyObject = {};
class View extends Component {
static displayName = 'View';
@@ -63,9 +25,9 @@ class View extends Component {
};
getChildContext() {
return {
isInAButtonView: this.props.accessibilityRole === 'button'
};
const isInAButtonView = this.props.accessibilityRole === 'button' ||
this.context.isInAButtonView;
return isInAButtonView ? { isInAButtonView } : emptyObject;
}
render() {
@@ -87,9 +49,6 @@ class View extends Component {
const component = this.context.isInAButtonView ? 'span' : 'div';
// DOM events need to be normalized to expect RN format
normalizeEventHandlers(otherProps);
otherProps.style = [styles.initial, style, pointerEvents && pointerEventStyles[pointerEvents]];
return createDOMElement(component, otherProps);

View File

@@ -5,24 +5,66 @@
* @flow
*/
import emptyFunction from 'fbjs/lib/emptyFunction';
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
import debounce from 'debounce';
const emptyObject = {};
const registry = {};
let id = 1;
const guid = () => `r-${id++}`;
if (canUseDOM) {
const triggerAll = () => {
Object.keys(registry).forEach(key => {
const instance = registry[key];
instance._handleLayout();
});
};
window.addEventListener('resize', debounce(triggerAll, 16), false);
}
const safeOverride = (original, next) => {
if (original) {
return function prototypeOverride() {
original.call(this);
next.call(this);
};
}
return next;
};
const applyLayout = Component => {
const componentDidMount = Component.prototype.componentDidMount || emptyFunction;
const componentDidUpdate = Component.prototype.componentDidUpdate || emptyFunction;
const componentDidMount = Component.prototype.componentDidMount;
const componentDidUpdate = Component.prototype.componentDidUpdate;
const componentWillUnmount = Component.prototype.componentWillUnmount;
Component.prototype.componentDidMount = function() {
componentDidMount.call(this);
this._layoutState = emptyObject;
this._handleLayout();
};
Component.prototype.componentDidMount = safeOverride(
componentDidMount,
function componentDidMount() {
this._layoutState = emptyObject;
this._isMounted = true;
this._onLayoutId = guid();
registry[this._onLayoutId] = this;
this._handleLayout();
}
);
Component.prototype.componentDidUpdate = function() {
componentDidUpdate.call(this);
this._handleLayout();
};
Component.prototype.componentDidUpdate = safeOverride(
componentDidUpdate,
function componentDidUpdate() {
this._handleLayout();
}
);
Component.prototype.componentWillUnmount = safeOverride(
componentWillUnmount,
function componentWillUnmount() {
this._isMounted = false;
delete registry[this._onLayoutId];
}
);
Component.prototype._handleLayout = function() {
const layout = this._layoutState;
@@ -30,13 +72,14 @@ const applyLayout = Component => {
if (onLayout) {
this.measure((x, y, width, height) => {
if (!this._isMounted) return;
if (
layout.x !== x || layout.y !== y || layout.width !== width || layout.height !== height
) {
const nextLayout = { x, y, width, height };
const nativeEvent = { layout: nextLayout };
this._layoutState = { x, y, width, height };
const nativeEvent = { layout: this._layoutState };
onLayout({ nativeEvent, timeStamp: Date.now() });
this._layoutState = nextLayout;
}
});
}

View File

@@ -1,3 +1,6 @@
import '../injectResponderEventPlugin';
import normalizeNativeEvent from '../normalizeNativeEvent';
import React from 'react';
import StyleRegistry from '../../apis/StyleSheet/registry';
@@ -19,23 +22,64 @@ const roleComponents = {
region: 'section'
};
const eventHandlerNames = {
onClick: true,
onClickCapture: true,
onMoveShouldSetResponder: true,
onMoveShouldSetResponderCapture: true,
onResponderGrant: true,
onResponderMove: true,
onResponderReject: true,
onResponderRelease: true,
onResponderTerminate: true,
onResponderTerminationRequest: true,
onStartShouldSetResponder: true,
onStartShouldSetResponderCapture: true,
onTouchCancel: true,
onTouchCancelCapture: true,
onTouchEnd: true,
onTouchEndCapture: true,
onTouchMove: true,
onTouchMoveCapture: true,
onTouchStart: true,
onTouchStartCapture: true
};
const wrapEventHandler = handler => e => {
e.nativeEvent = normalizeNativeEvent(e.nativeEvent);
return handler(e);
};
const createDOMElement = (component, rnProps) => {
const {
accessibilityLabel,
accessibilityLiveRegion,
accessibilityRole,
accessible = true,
style: rnStyle, // we need to remove the RN styles from 'domProps'
style: rnStyle,
testID,
type,
...domProps
} = rnProps || emptyObject;
// use equivalent platform elements where possible
const accessibilityComponent = accessibilityRole && roleComponents[accessibilityRole];
const Component = accessibilityComponent || component;
// convert React Native styles to DOM styles
const { className, style } = StyleRegistry.resolve(rnStyle) || emptyObject;
// normalize DOM events to match React Native events
// TODO: move this out of the render path
for (const prop in domProps) {
if (Object.prototype.hasOwnProperty.call(domProps, prop)) {
const isEventHandler = typeof prop === 'function' && eventHandlerNames[prop];
if (isEventHandler) {
domProps[prop] = wrapEventHandler(prop);
}
}
}
if (!accessible) {
domProps['aria-hidden'] = true;
}

View File

@@ -303,7 +303,7 @@ arrify@^1.0.0, arrify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
asap@^2.0.5, asap@~2.0.3:
asap@~2.0.3:
version "2.0.5"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f"