Skip to content

Commit 160505b

Browse files
authored
ReactDOM.useEvent: Add more scaffolding for useEvent hook (#18271)
1 parent a3bf668 commit 160505b

File tree

10 files changed

+215
-1
lines changed

10 files changed

+215
-1
lines changed

packages/react-debug-tools/src/ReactDebugHooks.js

+16
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ type HookLogEntry = {
3939
...
4040
};
4141

42+
type ReactDebugListenerMap = {|
43+
clear: () => void,
44+
setListener: (instance: EventTarget, callback: ?(Event) => void) => void,
45+
|};
46+
4247
let hookLog: Array<HookLogEntry> = [];
4348

4449
// Primitives
@@ -256,6 +261,16 @@ function useTransition(
256261
return [callback => {}, false];
257262
}
258263

264+
const noOp = () => {};
265+
266+
function useEvent(event: any): ReactDebugListenerMap {
267+
hookLog.push({primitive: 'Event', stackError: new Error(), value: event});
268+
return {
269+
clear: noOp,
270+
setListener: noOp,
271+
};
272+
}
273+
259274
function useDeferredValue<T>(value: T, config: TimeoutConfig | null | void): T {
260275
// useDeferredValue() composes multiple hooks internally.
261276
// Advance the current hook index the same number of times
@@ -285,6 +300,7 @@ const Dispatcher: DispatcherType = {
285300
useResponder,
286301
useTransition,
287302
useDeferredValue,
303+
useEvent,
288304
};
289305

290306
// Inspect

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

+7
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ import type {
5151
ReactDOMEventResponder,
5252
ReactDOMEventResponderInstance,
5353
ReactDOMFundamentalComponentInstance,
54+
ReactDOMListener,
55+
ReactDOMListenerEvent,
56+
ReactDOMListenerMap,
5457
} from 'shared/ReactDOMTypes';
5558
import {
5659
mountEventResponder,
@@ -70,6 +73,10 @@ import {
7073
IS_PASSIVE,
7174
} from 'legacy-events/EventSystemFlags';
7275

76+
export type ReactListenerEvent = ReactDOMListenerEvent;
77+
export type ReactListenerMap = ReactDOMListenerMap;
78+
export type ReactListener = ReactDOMListener;
79+
7380
export type Type = string;
7481
export type Props = {
7582
autoFocus?: boolean,

packages/react-dom/src/events/DOMModernPluginEventSystem.js

+9
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type {EventSystemFlags} from 'legacy-events/EventSystemFlags';
1313
import type {Fiber} from 'react-reconciler/src/ReactFiber';
1414
import type {PluginModule} from 'legacy-events/PluginModuleType';
1515
import type {ReactSyntheticEvent} from 'legacy-events/ReactSyntheticEventType';
16+
import type {ReactDOMListener} from 'shared/ReactDOMTypes';
1617

1718
import {registrationNameDependencies} from 'legacy-events/EventPluginRegistry';
1819
import {batchedEventUpdates} from 'legacy-events/ReactGenericBatching';
@@ -296,3 +297,11 @@ export function dispatchEventForPluginEventSystem(
296297
),
297298
);
298299
}
300+
301+
export function attachElementListener(listener: ReactDOMListener): void {
302+
// TODO
303+
}
304+
305+
export function detachElementListener(listener: ReactDOMListener): void {
306+
// TODO
307+
}

packages/react-dom/src/events/__tests__/DOMModernPluginEventSystem-test.internal.js

+36
Original file line numberDiff line numberDiff line change
@@ -1039,4 +1039,40 @@ describe('DOMModernPluginEventSystem', () => {
10391039
expect(log).toEqual([]);
10401040
expect(onDivClick).toHaveBeenCalledTimes(0);
10411041
});
1042+
1043+
describe('ReactDOM.useEvent', () => {
1044+
beforeEach(() => {
1045+
jest.resetModules();
1046+
ReactFeatureFlags = require('shared/ReactFeatureFlags');
1047+
ReactFeatureFlags.enableModernEventSystem = true;
1048+
ReactFeatureFlags.enableUseEventAPI = true;
1049+
1050+
React = require('react');
1051+
ReactDOM = require('react-dom');
1052+
Scheduler = require('scheduler');
1053+
ReactDOMServer = require('react-dom/server');
1054+
});
1055+
1056+
if (!__EXPERIMENTAL__) {
1057+
it("empty test so Jest doesn't complain", () => {});
1058+
return;
1059+
}
1060+
1061+
it('should create the same event listener map', () => {
1062+
let listenerMaps = [];
1063+
1064+
function Test() {
1065+
const listenerMap = ReactDOM.unstable_useEvent('click');
1066+
1067+
listenerMaps.push(listenerMap);
1068+
1069+
return <div />;
1070+
}
1071+
1072+
ReactDOM.render(<Test />, container);
1073+
ReactDOM.render(<Test />, container);
1074+
expect(listenerMaps.length).toEqual(2);
1075+
expect(listenerMaps[0]).toEqual(listenerMaps[1]);
1076+
});
1077+
});
10421078
});

packages/react-dom/src/server/ReactPartialRendererHooks.js

+10
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import type {
1717
ReactEventResponderListener,
1818
} from 'shared/ReactTypes';
1919
import type {SuspenseConfig} from 'react-reconciler/src/ReactFiberSuspenseConfig';
20+
import type {ReactDOMListenerMap} from 'shared/ReactDOMTypes';
21+
2022
import {validateContextBounds} from './ReactPartialRendererContext';
2123

2224
import invariant from 'shared/invariant';
@@ -474,6 +476,13 @@ function useTransition(
474476
return [startTransition, false];
475477
}
476478

479+
function useEvent(event: any): ReactDOMListenerMap {
480+
return {
481+
clear: noop,
482+
setListener: noop,
483+
};
484+
}
485+
477486
function noop(): void {}
478487

479488
export let currentThreadID: ThreadID = 0;
@@ -500,4 +509,5 @@ export const Dispatcher: DispatcherType = {
500509
useResponder,
501510
useDeferredValue,
502511
useTransition,
512+
useEvent,
503513
};

packages/react-native-renderer/src/ReactFabricHostConfig.js

+4
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ export type UpdatePayload = Object;
7676
export type TimeoutHandle = TimeoutID;
7777
export type NoTimeout = -1;
7878

79+
export type ReactListenerEvent = Object;
80+
export type ReactListenerMap = Object;
81+
export type ReactListener = Object;
82+
7983
// TODO: Remove this conditional once all changes have propagated.
8084
if (registerEventHandler) {
8185
/**

packages/react-native-renderer/src/ReactNativeHostConfig.js

+4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ import ReactNativeFiberHostComponent from './ReactNativeFiberHostComponent';
2626

2727
const {get: getViewConfigForType} = ReactNativeViewConfigRegistry;
2828

29+
export type ReactListenerEvent = Object;
30+
export type ReactListenerMap = Object;
31+
export type ReactListener = Object;
32+
2933
export type Type = string;
3034
export type Props = Object;
3135
export type Container = number;

0 commit comments

Comments
 (0)