Skip to content

Commit 2953425

Browse files
authored
ReactDOM.useEvent add flag and entry point (#18267)
1 parent 704c8b0 commit 2953425

12 files changed

+122
-0
lines changed

packages/react-dom/src/client/ReactDOM.js

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
unmountComponentAtNode,
2121
} from './ReactDOMLegacy';
2222
import {createRoot, createBlockingRoot, isValidContainer} from './ReactDOMRoot';
23+
import {useEvent} from './ReactDOMUseEvent';
2324

2425
import {
2526
batchedEventUpdates,
@@ -218,6 +219,8 @@ export {
218219
// Temporary alias since we already shipped React 16 RC with it.
219220
// TODO: remove in React 17.
220221
unstable_createPortal,
222+
// enableUseEventAPI
223+
useEvent as unstable_useEvent,
221224
};
222225

223226
const foundDevTools = injectIntoDevTools({
Original file line numberDiff line numberDiff line change
@@ -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
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,17 @@ export function getEventPriorityForPluginSystem(
223223
// for the event.
224224
return priority === undefined ? ContinuousEvent : priority;
225225
}
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
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,23 @@ export type ReactDOMResponderContext = {
7575
getResponderNode(): Element | null,
7676
...
7777
};
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
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ export const enableFundamentalAPI = false;
6060
// Experimental Scope support.
6161
export const enableScopeAPI = false;
6262

63+
// Experimental useEvent support.
64+
export const enableUseEventAPI = false;
65+
6366
// New API for JSX transforms to target - https://github.com/reactjs/rfcs/pull/107
6467

6568
// We will enforce mocking scheduler with scheduler/unstable_mock at some point. (v17?)

packages/shared/forks/ReactFeatureFlags.native-fb.js

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export const warnAboutDeprecatedLifecycles = true;
3030
export const enableDeprecatedFlareAPI = false;
3131
export const enableFundamentalAPI = false;
3232
export const enableScopeAPI = false;
33+
export const enableUseEventAPI = false;
3334
export const warnAboutUnmockedScheduler = true;
3435
export const flushSuspenseFallbacksInTests = true;
3536
export const enableSuspenseCallback = false;

packages/shared/forks/ReactFeatureFlags.native-oss.js

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export const enableSchedulerDebugging = false;
2929
export const enableDeprecatedFlareAPI = false;
3030
export const enableFundamentalAPI = false;
3131
export const enableScopeAPI = false;
32+
export const enableUseEventAPI = false;
3233
export const warnAboutUnmockedScheduler = false;
3334
export const flushSuspenseFallbacksInTests = true;
3435
export const enableSuspenseCallback = false;

packages/shared/forks/ReactFeatureFlags.test-renderer.js

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export const enableSchedulerDebugging = false;
2929
export const enableDeprecatedFlareAPI = false;
3030
export const enableFundamentalAPI = false;
3131
export const enableScopeAPI = false;
32+
export const enableUseEventAPI = false;
3233
export const warnAboutUnmockedScheduler = false;
3334
export const flushSuspenseFallbacksInTests = true;
3435
export const enableSuspenseCallback = false;

packages/shared/forks/ReactFeatureFlags.test-renderer.www.js

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export const disableInputAttributeSyncing = false;
2929
export const enableDeprecatedFlareAPI = true;
3030
export const enableFundamentalAPI = false;
3131
export const enableScopeAPI = true;
32+
export const enableUseEventAPI = false;
3233
export const warnAboutUnmockedScheduler = true;
3334
export const flushSuspenseFallbacksInTests = true;
3435
export const enableSuspenseCallback = true;

packages/shared/forks/ReactFeatureFlags.testing.js

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export const enableSchedulerDebugging = false;
2929
export const enableDeprecatedFlareAPI = false;
3030
export const enableFundamentalAPI = false;
3131
export const enableScopeAPI = false;
32+
export const enableUseEventAPI = false;
3233
export const warnAboutUnmockedScheduler = false;
3334
export const flushSuspenseFallbacksInTests = true;
3435
export const enableSuspenseCallback = false;

packages/shared/forks/ReactFeatureFlags.testing.www.js

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export const enableSchedulerDebugging = false;
2929
export const enableDeprecatedFlareAPI = true;
3030
export const enableFundamentalAPI = false;
3131
export const enableScopeAPI = true;
32+
export const enableUseEventAPI = false;
3233
export const warnAboutUnmockedScheduler = true;
3334
export const flushSuspenseFallbacksInTests = true;
3435
export const enableSuspenseCallback = true;

packages/shared/forks/ReactFeatureFlags.www.js

+2
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ export const enableFundamentalAPI = false;
8888

8989
export const enableScopeAPI = true;
9090

91+
export const enableUseEventAPI = false;
92+
9193
export const warnAboutUnmockedScheduler = true;
9294

9395
export const enableSuspenseCallback = true;

0 commit comments

Comments
 (0)