Skip to content

Commit d1fc26f

Browse files
committed
[change] Replace the ResponderEventPlugin
Replaces the ResponderEventPlugin with useResponderEvents hook. Also removes the event "normalization" of mouse, touch, and click events. These events are not part of the responder system and will no longer be modified from what ReactDOM dispatches. Fix #1568 Fix #829 Fix #693
1 parent 9d4df09 commit d1fc26f

File tree

22 files changed

+3935
-666
lines changed

22 files changed

+3935
-666
lines changed

.eslintrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"$ReadOnly": false,
4040
"$ReadOnlyArray": false,
4141
"CSSStyleSheet": false,
42+
"HTMLElement": false,
4243
"HTMLInputElement": false,
4344
"ReactClass": false,
4445
"ReactComponent": false,

packages/react-native-web/src/exports/Text/index.js

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import css from '../StyleSheet/css';
1515
import setAndForwardRef from '../../modules/setAndForwardRef';
1616
import useElementLayout from '../../hooks/useElementLayout';
1717
import usePlatformMethods from '../../hooks/usePlatformMethods';
18+
import useResponderEvents from '../../hooks/useResponderEvents';
1819
import React, { forwardRef, useContext, useRef } from 'react';
1920
import StyleSheet from '../StyleSheet';
2021
import TextAncestorContext from './TextAncestorContext';
@@ -107,6 +108,24 @@ const Text = forwardRef<TextProps, *>((props, ref) => {
107108

108109
useElementLayout(hostRef, onLayout);
109110
usePlatformMethods(hostRef, ref, classList, style);
111+
useResponderEvents(hostRef, {
112+
onMoveShouldSetResponder,
113+
onMoveShouldSetResponderCapture,
114+
onResponderEnd,
115+
onResponderGrant,
116+
onResponderMove,
117+
onResponderReject,
118+
onResponderRelease,
119+
onResponderStart,
120+
onResponderTerminate,
121+
onResponderTerminationRequest,
122+
onScrollShouldSetResponder,
123+
onScrollShouldSetResponderCapture,
124+
onSelectionChangeShouldSetResponder,
125+
onSelectionChangeShouldSetResponderCapture,
126+
onStartShouldSetResponder,
127+
onStartShouldSetResponderCapture
128+
});
110129

111130
function createEnterHandler(fn) {
112131
return e => {
@@ -138,29 +157,13 @@ const Text = forwardRef<TextProps, *>((props, ref) => {
138157
importantForAccessibility,
139158
nativeID,
140159
onBlur,
160+
onContextMenu,
141161
onFocus,
142-
onMoveShouldSetResponder,
143-
onMoveShouldSetResponderCapture,
144-
onResponderEnd,
145-
onResponderGrant,
146-
onResponderMove,
147-
onResponderReject,
148-
onResponderRelease,
149-
onResponderStart,
150-
onResponderTerminate,
151-
onResponderTerminationRequest,
152-
onScrollShouldSetResponder,
153-
onScrollShouldSetResponderCapture,
154-
onSelectionChangeShouldSetResponder,
155-
onSelectionChangeShouldSetResponderCapture,
156-
onStartShouldSetResponder,
157-
onStartShouldSetResponderCapture,
158162
ref: setRef,
159163
style,
160164
testID,
161165
// unstable
162166
onClick: onPress != null ? createPressHandler(onPress) : null,
163-
onContextMenu,
164167
onKeyDown: onPress != null ? createEnterHandler(onPress) : null,
165168
onMouseDown,
166169
onMouseEnter,

packages/react-native-web/src/exports/Text/types.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ export type TextProps = {
115115
onResponderRelease?: (e: any) => void,
116116
onResponderStart?: (e: any) => void,
117117
onResponderTerminate?: (e: any) => void,
118-
onResponderTerminationRequest?: (e: any) => void,
118+
onResponderTerminationRequest?: (e: any) => boolean,
119119
onScrollShouldSetResponder?: (e: any) => boolean,
120120
onScrollShouldSetResponderCapture?: (e: any) => boolean,
121121
onSelectionChangeShouldSetResponder?: (e: any) => boolean,

packages/react-native-web/src/exports/TextInput/index.js

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import setAndForwardRef from '../../modules/setAndForwardRef';
1616
import useElementLayout from '../../hooks/useElementLayout';
1717
import useLayoutEffect from '../../hooks/useLayoutEffect';
1818
import { usePlatformInputMethods } from '../../hooks/usePlatformMethods';
19+
import useResponderEvents from '../../hooks/useResponderEvents';
1920
import { forwardRef, useRef } from 'react';
2021
import StyleSheet from '../StyleSheet';
2122
import TextInputState from '../../modules/TextInputState';
@@ -286,6 +287,24 @@ const TextInput = forwardRef<TextInputProps, *>((props, ref) => {
286287

287288
useElementLayout(hostRef, onLayout);
288289
usePlatformInputMethods(hostRef, ref, classList, style);
290+
useResponderEvents(hostRef, {
291+
onMoveShouldSetResponder,
292+
onMoveShouldSetResponderCapture,
293+
onResponderEnd,
294+
onResponderGrant,
295+
onResponderMove,
296+
onResponderReject,
297+
onResponderRelease,
298+
onResponderStart,
299+
onResponderTerminate,
300+
onResponderTerminationRequest,
301+
onScrollShouldSetResponder,
302+
onScrollShouldSetResponderCapture,
303+
onSelectionChangeShouldSetResponder,
304+
onSelectionChangeShouldSetResponderCapture,
305+
onStartShouldSetResponder,
306+
onStartShouldSetResponderCapture
307+
});
289308

290309
return createElement(component, {
291310
accessibilityLabel,
@@ -310,22 +329,6 @@ const TextInput = forwardRef<TextInputProps, *>((props, ref) => {
310329
onKeyDown: handleKeyDown,
311330
onScroll,
312331
onSelect: handleSelectionChange,
313-
onMoveShouldSetResponder,
314-
onMoveShouldSetResponderCapture,
315-
onResponderEnd,
316-
onResponderGrant,
317-
onResponderMove,
318-
onResponderReject,
319-
onResponderRelease,
320-
onResponderStart,
321-
onResponderTerminate,
322-
onResponderTerminationRequest,
323-
onScrollShouldSetResponder,
324-
onScrollShouldSetResponderCapture,
325-
onSelectionChangeShouldSetResponder,
326-
onSelectionChangeShouldSetResponderCapture,
327-
onStartShouldSetResponder,
328-
onStartShouldSetResponderCapture,
329332
placeholder,
330333
pointerEvents,
331334
testID,

packages/react-native-web/src/exports/View/index.js

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import css from '../StyleSheet/css';
1515
import setAndForwardRef from '../../modules/setAndForwardRef';
1616
import useElementLayout from '../../hooks/useElementLayout';
1717
import usePlatformMethods from '../../hooks/usePlatformMethods';
18+
import useResponderEvents from '../../hooks/useResponderEvents';
1819
import StyleSheet from '../StyleSheet';
1920
import TextAncestorContext from '../Text/TextAncestorContext';
2021
import React, { forwardRef, useContext, useRef } from 'react';
@@ -132,21 +133,7 @@ const View = forwardRef<ViewProps, *>((props, ref) => {
132133

133134
useElementLayout(hostRef, onLayout);
134135
usePlatformMethods(hostRef, ref, classList, style);
135-
136-
return createElement('div', {
137-
accessibilityLabel,
138-
accessibilityLiveRegion,
139-
accessibilityRelationship,
140-
accessibilityRole,
141-
accessibilityState,
142-
accessibilityValue,
143-
children,
144-
classList,
145-
importantForAccessibility,
146-
nativeID,
147-
onBlur,
148-
onContextMenu,
149-
onFocus,
136+
useResponderEvents(hostRef, {
150137
onMoveShouldSetResponder,
151138
onMoveShouldSetResponderCapture,
152139
onResponderEnd,
@@ -162,7 +149,23 @@ const View = forwardRef<ViewProps, *>((props, ref) => {
162149
onSelectionChangeShouldSetResponder,
163150
onSelectionChangeShouldSetResponderCapture,
164151
onStartShouldSetResponder,
165-
onStartShouldSetResponderCapture,
152+
onStartShouldSetResponderCapture
153+
});
154+
155+
return createElement('div', {
156+
accessibilityLabel,
157+
accessibilityLiveRegion,
158+
accessibilityRelationship,
159+
accessibilityRole,
160+
accessibilityState,
161+
accessibilityValue,
162+
children,
163+
classList,
164+
importantForAccessibility,
165+
nativeID,
166+
onBlur,
167+
onContextMenu,
168+
onFocus,
166169
pointerEvents,
167170
ref: setRef,
168171
style,

packages/react-native-web/src/exports/View/types.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export type ViewProps = {
109109
onResponderRelease?: (e: any) => void,
110110
onResponderStart?: (e: any) => void,
111111
onResponderTerminate?: (e: any) => void,
112-
onResponderTerminationRequest?: (e: any) => void,
112+
onResponderTerminationRequest?: (e: any) => boolean,
113113
onScrollShouldSetResponder?: (e: any) => boolean,
114114
onScrollShouldSetResponderCapture?: (e: any) => boolean,
115115
onSelectionChangeShouldSetResponder?: (e: any) => boolean,
Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,5 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3-
exports[`modules/createElement normalizes event.nativeEvent 1`] = `
4-
Object {
5-
"_normalized": true,
6-
"bubbles": undefined,
7-
"cancelable": undefined,
8-
"changedTouches": Array [],
9-
"defaultPrevented": undefined,
10-
"identifier": undefined,
11-
"locationX": undefined,
12-
"locationY": undefined,
13-
"pageX": undefined,
14-
"pageY": undefined,
15-
"preventDefault": [Function],
16-
"stopImmediatePropagation": [Function],
17-
"stopPropagation": [Function],
18-
"target": undefined,
19-
"timestamp": 1496876171255,
20-
"touches": Array [],
21-
"type": undefined,
22-
"which": undefined,
23-
}
24-
`;
25-
263
exports[`modules/createElement renders different DOM elements 1`] = `<span />`;
274

285
exports[`modules/createElement renders different DOM elements 2`] = `<main />`;

packages/react-native-web/src/exports/createElement/__tests__/index-test.js

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,6 @@ describe('modules/createElement', () => {
1212
expect(component).toMatchSnapshot();
1313
});
1414

15-
test('normalizes event.nativeEvent', done => {
16-
const onClick = e => {
17-
e.nativeEvent.timestamp = 1496876171255;
18-
expect(e.nativeEvent).toMatchSnapshot();
19-
done();
20-
};
21-
const component = shallow(createElement('span', { onClick }));
22-
component.find('span').simulate('click', {
23-
nativeEvent: {}
24-
});
25-
});
26-
2715
describe('prop "accessibilityRole"', () => {
2816
test('and string component type', () => {
2917
const component = shallow(createElement('span', { accessibilityRole: 'link' }));

packages/react-native-web/src/exports/createElement/index.js

Lines changed: 4 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -8,77 +8,18 @@
88
*/
99

1010
import AccessibilityUtil from '../../modules/AccessibilityUtil';
11-
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
1211
import createDOMProps from '../../modules/createDOMProps';
13-
import { injectEventPluginsByName } from 'react-dom/unstable-native-dependencies';
14-
import normalizeNativeEvent from '../../modules/normalizeNativeEvent';
1512
import React from 'react';
16-
import ResponderEventPlugin from '../../modules/ResponderEventPlugin';
1713

18-
if (canUseDOM) {
19-
injectEventPluginsByName({
20-
ResponderEventPlugin
21-
});
22-
}
23-
24-
const isModifiedEvent = event =>
25-
!!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
26-
27-
/**
28-
* Ensure event handlers receive an event of the expected shape. The 'button'
29-
* role – for accessibility reasons and functional equivalence to the native
30-
* button element – must also support synthetic keyboard activation of onclick,
31-
* and remove event handlers when disabled.
32-
*/
33-
const eventHandlerNames = {
34-
onBlur: true,
35-
onClick: true,
36-
onClickCapture: true,
37-
onContextMenu: true,
38-
onFocus: true,
39-
onResponderRelease: true,
40-
onTouchCancel: true,
41-
onTouchCancelCapture: true,
42-
onTouchEnd: true,
43-
onTouchEndCapture: true,
44-
onTouchMove: true,
45-
onTouchMoveCapture: true,
46-
onTouchStart: true,
47-
onTouchStartCapture: true
48-
};
4914
const adjustProps = domProps => {
50-
const { onClick, onResponderRelease, role } = domProps;
15+
const { onClick, role } = domProps;
5116

5217
const isButtonLikeRole = AccessibilityUtil.buttonLikeRoles[role];
5318
const isDisabled = AccessibilityUtil.isDisabled(domProps);
54-
const isLinkRole = role === 'link';
5519

56-
Object.keys(domProps).forEach(propName => {
57-
const prop = domProps[propName];
58-
const isEventHandler = typeof prop === 'function' && eventHandlerNames[propName];
59-
if (isEventHandler) {
60-
if (isButtonLikeRole && isDisabled) {
61-
domProps[propName] = undefined;
62-
} else {
63-
// TODO: move this out of the render path
64-
domProps[propName] = e => {
65-
e.nativeEvent = normalizeNativeEvent(e.nativeEvent);
66-
return prop(e);
67-
};
68-
}
69-
}
70-
});
71-
72-
// Cancel click events if the responder system is being used on a link
73-
// element. Click events are not an expected part of the React Native API,
74-
// and browsers dispatch click events that cannot otherwise be cancelled from
75-
// preceding mouse events in the responder system.
76-
if (isLinkRole && onResponderRelease) {
77-
domProps.onClick = function(e) {
78-
if (!e.isDefaultPrevented() && !isModifiedEvent(e.nativeEvent) && !domProps.target) {
79-
e.preventDefault();
80-
}
81-
};
20+
// Button-like roles should not trigger 'onClick' if they are disabled.
21+
if (isButtonLikeRole && isDisabled && domProps.onClick != null) {
22+
domProps.onClick = undefined;
8223
}
8324

8425
// Button-like roles should trigger 'onClick' if SPACE or ENTER keys are pressed.

0 commit comments

Comments
 (0)