mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-06-02 02:25:22 +00:00
[change] prevent default click behavior when using responder system
Certain HTML elements have a default behaviour (e.g., link navigation)
that can only be prevented in the `click` event handler. The responder
event system doesn't make use of `click` and no callbacks have access to
the `click` event. To prevent unwanted default behaviour, and emulate
the behavior in React Native, the `click` callback will automatically
call `preventDefault()` when the responder system is being used.
The result is that components like `Touchable*` that are overloaded as
web links need to explicitly trigger the link navigation, e.g.,
```
<TouchableOpacity
accessibilityTraits="link"
href={href}
onPress={(e) => {
Linking.openUrl(href);
}}
/>
```
Fix #970
This commit is contained in:
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`modules/createElement it normalizes event.nativeEvent 1`] = `
|
exports[`modules/createElement normalizes event.nativeEvent 1`] = `
|
||||||
Object {
|
Object {
|
||||||
"_normalized": true,
|
"_normalized": true,
|
||||||
"bubbles": undefined,
|
"bubbles": undefined,
|
||||||
@@ -23,6 +23,6 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`modules/createElement it renders different DOM elements 1`] = `<span />`;
|
exports[`modules/createElement renders different DOM elements 1`] = `<span />`;
|
||||||
|
|
||||||
exports[`modules/createElement it renders different DOM elements 2`] = `<main />`;
|
exports[`modules/createElement renders different DOM elements 2`] = `<main />`;
|
||||||
|
|||||||
+2
-2
@@ -5,14 +5,14 @@ import React from 'react';
|
|||||||
import { render, shallow } from 'enzyme';
|
import { render, shallow } from 'enzyme';
|
||||||
|
|
||||||
describe('modules/createElement', () => {
|
describe('modules/createElement', () => {
|
||||||
test('it renders different DOM elements', () => {
|
test('renders different DOM elements', () => {
|
||||||
let component = render(createElement('span'));
|
let component = render(createElement('span'));
|
||||||
expect(component).toMatchSnapshot();
|
expect(component).toMatchSnapshot();
|
||||||
component = render(createElement('main'));
|
component = render(createElement('main'));
|
||||||
expect(component).toMatchSnapshot();
|
expect(component).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('it normalizes event.nativeEvent', done => {
|
test('normalizes event.nativeEvent', done => {
|
||||||
const onClick = e => {
|
const onClick = e => {
|
||||||
e.nativeEvent.timestamp = 1496876171255;
|
e.nativeEvent.timestamp = 1496876171255;
|
||||||
expect(e.nativeEvent).toMatchSnapshot();
|
expect(e.nativeEvent).toMatchSnapshot();
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ EventPluginHub.injection.injectEventPluginsByName({
|
|||||||
ResponderEventPlugin
|
ResponderEventPlugin
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const isModifiedEvent = event =>
|
||||||
|
!!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure event handlers receive an event of the expected shape. The 'button'
|
* Ensure event handlers receive an event of the expected shape. The 'button'
|
||||||
* role – for accessibility reasons and functional equivalence to the native
|
* role – for accessibility reasons and functional equivalence to the native
|
||||||
@@ -43,7 +46,9 @@ const eventHandlerNames = {
|
|||||||
onTouchStartCapture: true
|
onTouchStartCapture: true
|
||||||
};
|
};
|
||||||
const adjustProps = domProps => {
|
const adjustProps = domProps => {
|
||||||
const isButtonRole = domProps.role === 'button';
|
const { onClick, onResponderRelease, role } = domProps;
|
||||||
|
|
||||||
|
const isButtonRole = role === 'button';
|
||||||
const isDisabled = AccessibilityUtil.isDisabled(domProps);
|
const isDisabled = AccessibilityUtil.isDisabled(domProps);
|
||||||
|
|
||||||
Object.keys(domProps).forEach(propName => {
|
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) {
|
if (isButtonRole && !isDisabled) {
|
||||||
const { onClick } = domProps;
|
|
||||||
domProps.onKeyPress = function(e) {
|
domProps.onKeyPress = function(e) {
|
||||||
if (!e.isDefaultPrevented() && (e.which === 13 || e.which === 32)) {
|
if (!e.isDefaultPrevented() && (e.which === 13 || e.which === 32)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|||||||
Reference in New Issue
Block a user