Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ReactDOM.useEvent add flag and entry point #18267

Merged
merged 1 commit into from Mar 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/react-dom/src/client/ReactDOM.js
Expand Up @@ -20,6 +20,7 @@ import {
unmountComponentAtNode,
} from './ReactDOMLegacy';
import {createRoot, createBlockingRoot, isValidContainer} from './ReactDOMRoot';
import {useEvent} from './ReactDOMUseEvent';

import {
batchedEventUpdates,
Expand Down Expand Up @@ -218,6 +219,8 @@ export {
// Temporary alias since we already shipped React 16 RC with it.
// TODO: remove in React 17.
unstable_createPortal,
// enableUseEventAPI
useEvent as unstable_useEvent,
};

const foundDevTools = injectIntoDevTools({
Expand Down
74 changes: 74 additions & 0 deletions packages/react-dom/src/client/ReactDOMUseEvent.js
@@ -0,0 +1,74 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

import type {EventPriority} from 'shared/ReactTypes';
import type {
ReactDOMListenerEvent,
ReactDOMListenerMap,
} from 'shared/ReactDOMTypes';

import ReactSharedInternals from 'shared/ReactSharedInternals';
import invariant from 'shared/invariant';

import {getEventPriorityForListenerSystem} from '../events/DOMEventProperties';

type EventOptions = {|
capture?: boolean,
passive?: boolean,
priority?: EventPriority,
|};

const {ReactCurrentDispatcher} = ReactSharedInternals;

function resolveDispatcher() {
const dispatcher = ReactCurrentDispatcher.current;
invariant(
dispatcher !== null,
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
' one of the following reasons:\n' +
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
'2. You might be breaking the Rules of Hooks\n' +
'3. You might have more than one copy of React in the same app\n' +
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
);
return dispatcher;
}

export function useEvent(
type: string,
options?: EventOptions,
): ReactDOMListenerMap {
const dispatcher = resolveDispatcher();
let capture = false;
let passive = false;
let priority = getEventPriorityForListenerSystem((type: any));

if (options != null) {
const optionsCapture = options.capture;
const optionsPassive = options.passive;
const optionsPriority = options.priority;

if (typeof optionsCapture === 'boolean') {
capture = optionsCapture;
}
if (typeof optionsPassive === 'boolean') {
passive = optionsPassive;
}
if (typeof optionsPriority === 'number') {
priority = optionsPriority;
}
}
const event: ReactDOMListenerEvent = {
capture,
passive,
priority,
type,
};
return dispatcher.useEvent(event);
}
14 changes: 14 additions & 0 deletions packages/react-dom/src/events/DOMEventProperties.js
Expand Up @@ -223,3 +223,17 @@ export function getEventPriorityForPluginSystem(
// for the event.
return priority === undefined ? ContinuousEvent : priority;
}

export function getEventPriorityForListenerSystem(type: string): EventPriority {
const priority = eventPriorities.get(((type: any): TopLevelType));
if (priority !== undefined) {
return priority;
}
if (__DEV__) {
console.warn(
'The event "type" provided to useEvent() does not have a known priority type.' +
' It is recommended to provide a "priority" option to specify a priority.',
);
}
return ContinuousEvent;
}
20 changes: 20 additions & 0 deletions packages/shared/ReactDOMTypes.js
Expand Up @@ -75,3 +75,23 @@ export type ReactDOMResponderContext = {
getResponderNode(): Element | null,
...
};

export type ReactDOMListenerEvent = {|
capture: boolean,
passive: boolean,
priority: EventPriority,
type: string,
|};

export type ReactDOMListenerMap = {|
clear: () => void,
setListener: (instance: EventTarget, callback: ?(Event) => void) => void,
|};

export type ReactDOMListener = {|
callback: Event => void,
depth: number,
destroy: Document | (Element => void),
event: ReactDOMListenerEvent,
instance: EventTarget,
|};
3 changes: 3 additions & 0 deletions packages/shared/ReactFeatureFlags.js
Expand Up @@ -60,6 +60,9 @@ export const enableFundamentalAPI = false;
// Experimental Scope support.
export const enableScopeAPI = false;

// Experimental useEvent support.
export const enableUseEventAPI = false;

// New API for JSX transforms to target - https://github.com/reactjs/rfcs/pull/107

// We will enforce mocking scheduler with scheduler/unstable_mock at some point. (v17?)
Expand Down
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.native-fb.js
Expand Up @@ -30,6 +30,7 @@ export const warnAboutDeprecatedLifecycles = true;
export const enableDeprecatedFlareAPI = false;
export const enableFundamentalAPI = false;
export const enableScopeAPI = false;
export const enableUseEventAPI = false;
export const warnAboutUnmockedScheduler = true;
export const flushSuspenseFallbacksInTests = true;
export const enableSuspenseCallback = false;
Expand Down
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.native-oss.js
Expand Up @@ -29,6 +29,7 @@ export const enableSchedulerDebugging = false;
export const enableDeprecatedFlareAPI = false;
export const enableFundamentalAPI = false;
export const enableScopeAPI = false;
export const enableUseEventAPI = false;
export const warnAboutUnmockedScheduler = false;
export const flushSuspenseFallbacksInTests = true;
export const enableSuspenseCallback = false;
Expand Down
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.test-renderer.js
Expand Up @@ -29,6 +29,7 @@ export const enableSchedulerDebugging = false;
export const enableDeprecatedFlareAPI = false;
export const enableFundamentalAPI = false;
export const enableScopeAPI = false;
export const enableUseEventAPI = false;
export const warnAboutUnmockedScheduler = false;
export const flushSuspenseFallbacksInTests = true;
export const enableSuspenseCallback = false;
Expand Down
Expand Up @@ -29,6 +29,7 @@ export const disableInputAttributeSyncing = false;
export const enableDeprecatedFlareAPI = true;
export const enableFundamentalAPI = false;
export const enableScopeAPI = true;
export const enableUseEventAPI = false;
export const warnAboutUnmockedScheduler = true;
export const flushSuspenseFallbacksInTests = true;
export const enableSuspenseCallback = true;
Expand Down
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.testing.js
Expand Up @@ -29,6 +29,7 @@ export const enableSchedulerDebugging = false;
export const enableDeprecatedFlareAPI = false;
export const enableFundamentalAPI = false;
export const enableScopeAPI = false;
export const enableUseEventAPI = false;
export const warnAboutUnmockedScheduler = false;
export const flushSuspenseFallbacksInTests = true;
export const enableSuspenseCallback = false;
Expand Down
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.testing.www.js
Expand Up @@ -29,6 +29,7 @@ export const enableSchedulerDebugging = false;
export const enableDeprecatedFlareAPI = true;
export const enableFundamentalAPI = false;
export const enableScopeAPI = true;
export const enableUseEventAPI = false;
export const warnAboutUnmockedScheduler = true;
export const flushSuspenseFallbacksInTests = true;
export const enableSuspenseCallback = true;
Expand Down
2 changes: 2 additions & 0 deletions packages/shared/forks/ReactFeatureFlags.www.js
Expand Up @@ -88,6 +88,8 @@ export const enableFundamentalAPI = false;

export const enableScopeAPI = true;

export const enableUseEventAPI = false;

export const warnAboutUnmockedScheduler = true;

export const enableSuspenseCallback = true;
Expand Down