diff --git a/packages/react-dom/src/client/ReactDOMComponentTree.js b/packages/react-dom/src/client/ReactDOMComponentTree.js index d5f09c1caf45d..d0edca73baee5 100644 --- a/packages/react-dom/src/client/ReactDOMComponentTree.js +++ b/packages/react-dom/src/client/ReactDOMComponentTree.js @@ -9,7 +9,10 @@ import type {Fiber} from 'react-reconciler/src/ReactInternalTypes'; import type {ReactScopeInstance} from 'shared/ReactTypes'; -import type {ReactDOMEventHandleListener} from '../shared/ReactDOMTypes'; +import type { + ReactDOMEventHandle, + ReactDOMEventHandleListener, +} from '../shared/ReactDOMTypes'; import type { Container, TextInstance, @@ -39,6 +42,7 @@ const internalPropsKey = '__reactProps$' + randomKey; const internalContainerInstanceKey = '__reactContainer$' + randomKey; const internalEventHandlersKey = '__reactEvents$' + randomKey; const internalEventHandlerListenersKey = '__reactListeners$' + randomKey; +const internalEventHandlesSetKey = '__reactHandles$' + randomKey; export type ElementListenerMap = Map< DOMEventName | string, @@ -232,3 +236,25 @@ export function getEventHandlerListeners( ): null | Set { return (scope: any)[internalEventHandlerListenersKey] || null; } + +export function addEventHandleToTarget( + target: EventTarget | ReactScopeInstance, + eventHandle: ReactDOMEventHandle, +): void { + let eventHandles = (target: any)[internalEventHandlesSetKey]; + if (eventHandles === undefined) { + eventHandles = (target: any)[internalEventHandlesSetKey] = new Set(); + } + eventHandles.add(eventHandle); +} + +export function doesTargetHaveEventHandle( + target: EventTarget | ReactScopeInstance, + eventHandle: ReactDOMEventHandle, +): boolean { + const eventHandles = (target: any)[internalEventHandlesSetKey]; + if (eventHandles === undefined) { + return false; + } + return eventHandles.has(eventHandle); +} diff --git a/packages/react-dom/src/client/ReactDOMEventHandle.js b/packages/react-dom/src/client/ReactDOMEventHandle.js index 19e69126aef0c..303b083313e98 100644 --- a/packages/react-dom/src/client/ReactDOMEventHandle.js +++ b/packages/react-dom/src/client/ReactDOMEventHandle.js @@ -20,6 +20,8 @@ import { getEventHandlerListeners, setEventHandlerListeners, getFiberFromScopeInstance, + doesTargetHaveEventHandle, + addEventHandleToTarget, } from './ReactDOMComponentTree'; import {ELEMENT_NODE, COMMENT_NODE} from '../shared/HTMLNodeType'; import { @@ -42,8 +44,6 @@ type EventHandleOptions = {| priority?: EventPriority, |}; -const PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set; - function getNearestRootOrPortalContainer(node: Fiber): null | Element { while (node !== null) { const tag = node.tag; @@ -201,9 +201,7 @@ export function createEventHandle( listenerPriority = getEventPriorityForListenerSystem(domEventName); } - const registeredReactDOMEvents = new PossiblyWeakSet(); - - return ( + const eventHandle = ( target: EventTarget | ReactScopeInstance, callback: (SyntheticEvent) => void, ) => { @@ -212,8 +210,8 @@ export function createEventHandle( 'ReactDOM.createEventHandle: setter called with an invalid ' + 'callback. The callback must be a function.', ); - if (!registeredReactDOMEvents.has(target)) { - registeredReactDOMEvents.add(target); + if (!doesTargetHaveEventHandle(target, eventHandle)) { + addEventHandleToTarget(target, eventHandle); registerReactDOMEvent( target, domEventName, @@ -241,6 +239,8 @@ export function createEventHandle( ); }; }; + + return eventHandle; } return (null: any); }