Skip to content

Commit 31ecf51

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 #1571 Fix #829 Fix #693
1 parent 200890c commit 31ecf51

File tree

22 files changed

+4045
-672
lines changed

22 files changed

+4045
-672
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 & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -8,83 +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-
try {
20-
injectEventPluginsByName({
21-
ResponderEventPlugin
22-
});
23-
} catch (error) {
24-
// Ignore errors caused by attempting to re-inject the plugin when app
25-
// scripts are being re-evaluated (e.g., development hot reloading) while
26-
// the ReactDOM instance is preserved.
27-
}
28-
}
29-
30-
const isModifiedEvent = event =>
31-
!!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
32-
33-
/**
34-
* Ensure event handlers receive an event of the expected shape. The 'button'
35-
* role – for accessibility reasons and functional equivalence to the native
36-
* button element – must also support synthetic keyboard activation of onclick,
37-
* and remove event handlers when disabled.
38-
*/
39-
const eventHandlerNames = {
40-
onBlur: true,
41-
onClick: true,
42-
onClickCapture: true,
43-
onContextMenu: true,
44-
onFocus: true,
45-
onResponderRelease: true,
46-
onTouchCancel: true,
47-
onTouchCancelCapture: true,
48-
onTouchEnd: true,
49-
onTouchEndCapture: true,
50-
onTouchMove: true,
51-
onTouchMoveCapture: true,
52-
onTouchStart: true,
53-
onTouchStartCapture: true
54-
};
5514
const adjustProps = domProps => {
56-
const { onClick, onResponderRelease, role } = domProps;
15+
const { onClick, role } = domProps;
5716

5817
const isButtonLikeRole = AccessibilityUtil.buttonLikeRoles[role];
5918
const isDisabled = AccessibilityUtil.isDisabled(domProps);
60-
const isLinkRole = role === 'link';
6119

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

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

0 commit comments

Comments
 (0)