ReactDOM.useEvent add flag and entry point (#18267)
Dominic Gannaway committed
Mar 10, 2020 at 12:18 UTC
29534252add3b90f7984a0f1c89937ed32d36ceb
12 files changed
+122
packages/react-dom/src/client/ReactDOM.js
+3
@@ -20,6 +20,7 @@ import {
20
unmountComponentAtNode,
21
} from './ReactDOMLegacy';
22
import {createRoot, createBlockingRoot, isValidContainer} from './ReactDOMRoot';
23
+import {useEvent} from './ReactDOMUseEvent';
24
25
import {
26
batchedEventUpdates,
@@ -218,6 +219,8 @@ export {
219
// Temporary alias since we already shipped React 16 RC with it.
220
// TODO: remove in React 17.
221
unstable_createPortal,
222
+ // enableUseEventAPI
223
+ useEvent as unstable_useEvent,
224
};
225
226
const foundDevTools = injectIntoDevTools({
packages/react-dom/src/client/ReactDOMUseEvent.js
new
+74
@@ -0,0 +1,74 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+import type {EventPriority} from 'shared/ReactTypes';
11
+import type {
12
+ ReactDOMListenerEvent,
13
+ ReactDOMListenerMap,
14
+} from 'shared/ReactDOMTypes';
15
+
16
+import ReactSharedInternals from 'shared/ReactSharedInternals';
17
+import invariant from 'shared/invariant';
18
+
19
+import {getEventPriorityForListenerSystem} from '../events/DOMEventProperties';
20
+
21
+type EventOptions = {|
22
+ capture?: boolean,
23
+ passive?: boolean,
24
+ priority?: EventPriority,
25
+|};
26
+
27
+const {ReactCurrentDispatcher} = ReactSharedInternals;
28
+
29
+function resolveDispatcher() {
30
+ const dispatcher = ReactCurrentDispatcher.current;
31
+ invariant(
32
+ dispatcher !== null,
33
+ 'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
34
+ ' one of the following reasons:\n' +
35
+ '1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
36
+ '2. You might be breaking the Rules of Hooks\n' +
37
+ '3. You might have more than one copy of React in the same app\n' +
38
+ 'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
39
+ );
40
+ return dispatcher;
41
+}
42
+
43
+export function useEvent(
44
+ type: string,
45
+ options?: EventOptions,
46
+): ReactDOMListenerMap {
47
+ const dispatcher = resolveDispatcher();
48
+ let capture = false;
49
+ let passive = false;
50
+ let priority = getEventPriorityForListenerSystem((type: any));
51
+
52
+ if (options != null) {
53
+ const optionsCapture = options.capture;
54
+ const optionsPassive = options.passive;
55
+ const optionsPriority = options.priority;
56
+
57
+ if (typeof optionsCapture === 'boolean') {
58
+ capture = optionsCapture;
59
+ }
60
+ if (typeof optionsPassive === 'boolean') {
61
+ passive = optionsPassive;
62
+ }
63
+ if (typeof optionsPriority === 'number') {
64
+ priority = optionsPriority;
65
+ }
66
+ }
67
+ const event: ReactDOMListenerEvent = {
68
+ capture,
69
+ passive,
70
+ priority,
71
+ type,
72
+ };
73
+ return dispatcher.useEvent(event);
74
+}
packages/react-dom/src/events/DOMEventProperties.js
+14
@@ -223,3 +223,17 @@ export function getEventPriorityForPluginSystem(
223
// for the event.
224
return priority === undefined ? ContinuousEvent : priority;
225
}
226
+
227
+export function getEventPriorityForListenerSystem(type: string): EventPriority {
228
+ const priority = eventPriorities.get(((type: any): TopLevelType));
229
+ if (priority !== undefined) {
230
+ return priority;
231
+ }
232
+ if (__DEV__) {
233
+ console.warn(
234
+ 'The event "type" provided to useEvent() does not have a known priority type.' +
235
+ ' It is recommended to provide a "priority" option to specify a priority.',
236
+ );
237
+ }
238
+ return ContinuousEvent;
239
+}
packages/shared/ReactDOMTypes.js
+20
@@ -75,3 +75,23 @@ export type ReactDOMResponderContext = {
75
getResponderNode(): Element | null,
76
...
77
};
78
+
79
+export type ReactDOMListenerEvent = {|
80
+ capture: boolean,
81
+ passive: boolean,
82
+ priority: EventPriority,
83
+ type: string,
84
+|};
85
+
86
+export type ReactDOMListenerMap = {|
87
+ clear: () => void,
88
+ setListener: (instance: EventTarget, callback: ?(Event) => void) => void,
89
+|};
90
+
91
+export type ReactDOMListener = {|
92
+ callback: Event => void,
93
+ depth: number,
94
+ destroy: Document | (Element => void),
95
+ event: ReactDOMListenerEvent,
96
+ instance: EventTarget,
97
+|};
packages/shared/ReactFeatureFlags.js
+3
@@ -60,6 +60,9 @@ export const enableFundamentalAPI = false;
60
// Experimental Scope support.
61
export const enableScopeAPI = false;
62
63
+// Experimental useEvent support.
64
+export const enableUseEventAPI = false;
65
+
66
// New API for JSX transforms to target - https://github.com/reactjs/rfcs/pull/107
67
68
// We will enforce mocking scheduler with scheduler/unstable_mock at some point. (v17?)
packages/shared/forks/ReactFeatureFlags.native-fb.js
+1
@@ -30,6 +30,7 @@ export const warnAboutDeprecatedLifecycles = true;
30
export const enableDeprecatedFlareAPI = false;
31
export const enableFundamentalAPI = false;
32
export const enableScopeAPI = false;
33
+export const enableUseEventAPI = false;
34
export const warnAboutUnmockedScheduler = true;
35
export const flushSuspenseFallbacksInTests = true;
36
export const enableSuspenseCallback = false;
packages/shared/forks/ReactFeatureFlags.native-oss.js
+1
@@ -29,6 +29,7 @@ export const enableSchedulerDebugging = false;
29
export const enableDeprecatedFlareAPI = false;
30
export const enableFundamentalAPI = false;
31
export const enableScopeAPI = false;
32
+export const enableUseEventAPI = false;
33
export const warnAboutUnmockedScheduler = false;
34
export const flushSuspenseFallbacksInTests = true;
35
export const enableSuspenseCallback = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.js
+1
@@ -29,6 +29,7 @@ export const enableSchedulerDebugging = false;
29
export const enableDeprecatedFlareAPI = false;
30
export const enableFundamentalAPI = false;
31
export const enableScopeAPI = false;
32
+export const enableUseEventAPI = false;
33
export const warnAboutUnmockedScheduler = false;
34
export const flushSuspenseFallbacksInTests = true;
35
export const enableSuspenseCallback = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
+1
@@ -29,6 +29,7 @@ export const disableInputAttributeSyncing = false;
29
export const enableDeprecatedFlareAPI = true;
30
export const enableFundamentalAPI = false;
31
export const enableScopeAPI = true;
32
+export const enableUseEventAPI = false;
33
export const warnAboutUnmockedScheduler = true;
34
export const flushSuspenseFallbacksInTests = true;
35
export const enableSuspenseCallback = true;
packages/shared/forks/ReactFeatureFlags.testing.js
+1
@@ -29,6 +29,7 @@ export const enableSchedulerDebugging = false;
29
export const enableDeprecatedFlareAPI = false;
30
export const enableFundamentalAPI = false;
31
export const enableScopeAPI = false;
32
+export const enableUseEventAPI = false;
33
export const warnAboutUnmockedScheduler = false;
34
export const flushSuspenseFallbacksInTests = true;
35
export const enableSuspenseCallback = false;
packages/shared/forks/ReactFeatureFlags.testing.www.js
+1
@@ -29,6 +29,7 @@ export const enableSchedulerDebugging = false;
29
export const enableDeprecatedFlareAPI = true;
30
export const enableFundamentalAPI = false;
31
export const enableScopeAPI = true;
32
+export const enableUseEventAPI = false;
33
export const warnAboutUnmockedScheduler = true;
34
export const flushSuspenseFallbacksInTests = true;
35
export const enableSuspenseCallback = true;
packages/shared/forks/ReactFeatureFlags.www.js
+2
@@ -88,6 +88,8 @@ export const enableFundamentalAPI = false;
88
89
export const enableScopeAPI = true;
90
91
+export const enableUseEventAPI = false;
92
+
93
export const warnAboutUnmockedScheduler = true;
94
95
export const enableSuspenseCallback = true;