diff --git a/packages/react-native-web/src/exports/createElement/__tests__/__snapshots__/index-test.js.snap b/packages/react-native-web/src/exports/createElement/__tests__/__snapshots__/index-test.js.snap
index c86761eb..4b97c76d 100644
--- a/packages/react-native-web/src/exports/createElement/__tests__/__snapshots__/index-test.js.snap
+++ b/packages/react-native-web/src/exports/createElement/__tests__/__snapshots__/index-test.js.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`modules/createElement it normalizes event.nativeEvent 1`] = `
+exports[`modules/createElement normalizes event.nativeEvent 1`] = `
Object {
"_normalized": true,
"bubbles": undefined,
@@ -23,6 +23,6 @@ Object {
}
`;
-exports[`modules/createElement it renders different DOM elements 1`] = ``;
+exports[`modules/createElement renders different DOM elements 1`] = ``;
-exports[`modules/createElement it renders different DOM elements 2`] = ``;
+exports[`modules/createElement renders different DOM elements 2`] = ``;
diff --git a/packages/react-native-web/src/exports/createElement/__tests__/index-test.js b/packages/react-native-web/src/exports/createElement/__tests__/index-test.js
index bf75e2a9..a4d5db0d 100644
--- a/packages/react-native-web/src/exports/createElement/__tests__/index-test.js
+++ b/packages/react-native-web/src/exports/createElement/__tests__/index-test.js
@@ -5,14 +5,14 @@ import React from 'react';
import { render, shallow } from 'enzyme';
describe('modules/createElement', () => {
- test('it renders different DOM elements', () => {
+ test('renders different DOM elements', () => {
let component = render(createElement('span'));
expect(component).toMatchSnapshot();
component = render(createElement('main'));
expect(component).toMatchSnapshot();
});
- test('it normalizes event.nativeEvent', done => {
+ test('normalizes event.nativeEvent', done => {
const onClick = e => {
e.nativeEvent.timestamp = 1496876171255;
expect(e.nativeEvent).toMatchSnapshot();
diff --git a/packages/react-native-web/src/exports/createElement/index.js b/packages/react-native-web/src/exports/createElement/index.js
index 0020bf05..32780318 100644
--- a/packages/react-native-web/src/exports/createElement/index.js
+++ b/packages/react-native-web/src/exports/createElement/index.js
@@ -20,6 +20,9 @@ EventPluginHub.injection.injectEventPluginsByName({
ResponderEventPlugin
});
+const isModifiedEvent = event =>
+ !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
+
/**
* Ensure event handlers receive an event of the expected shape. The 'button'
* role – for accessibility reasons and functional equivalence to the native
@@ -43,7 +46,9 @@ const eventHandlerNames = {
onTouchStartCapture: true
};
const adjustProps = domProps => {
- const isButtonRole = domProps.role === 'button';
+ const { onClick, onResponderRelease, role } = domProps;
+
+ const isButtonRole = role === 'button';
const isDisabled = AccessibilityUtil.isDisabled(domProps);
Object.keys(domProps).forEach(propName => {
@@ -62,9 +67,20 @@ const adjustProps = domProps => {
}
});
- // Button role should trigger 'onClick' if SPACE or ENTER keys are pressed
+ // Cancel click events if the responder system is being used. Click events
+ // are not an expected part of the React Native API, and browsers dispatch
+ // click events that cannot otherwise be cancelled from preceding mouse
+ // events in the responder system.
+ if (onResponderRelease) {
+ domProps.onClick = function(e) {
+ if (!e.isDefaultPrevented() && !isModifiedEvent(e.nativeEvent) && !domProps.target) {
+ e.preventDefault();
+ }
+ };
+ }
+
+ // Button role should trigger 'onClick' if SPACE or ENTER keys are pressed.
if (isButtonRole && !isDisabled) {
- const { onClick } = domProps;
domProps.onKeyPress = function(e) {
if (!e.isDefaultPrevented() && (e.which === 13 || e.which === 32)) {
e.preventDefault();