mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
Refactor createEventHandle signature (#19174)
This commit is contained in:
4
packages/react-art/src/ReactARTHostConfig.js
vendored
4
packages/react-art/src/ReactARTHostConfig.js
vendored
@@ -469,10 +469,6 @@ export function getInstanceFromNode(node) {
|
||||
throw new Error('Not yet implemented.');
|
||||
}
|
||||
|
||||
export function removeInstanceEventHandles(instance) {
|
||||
// noop
|
||||
}
|
||||
|
||||
export function isOpaqueHydratingObject(value: mixed): boolean {
|
||||
throw new Error('Not yet implemented');
|
||||
}
|
||||
|
||||
194
packages/react-dom/src/client/ReactDOMEventHandle.js
vendored
194
packages/react-dom/src/client/ReactDOMEventHandle.js
vendored
@@ -47,6 +47,8 @@ type EventHandleOptions = {|
|
||||
priority?: EventPriority,
|
||||
|};
|
||||
|
||||
const PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set;
|
||||
|
||||
function getNearestRootOrPortalContainer(node: Fiber): null | Element {
|
||||
while (node !== null) {
|
||||
const tag = node.tag;
|
||||
@@ -72,12 +74,10 @@ function createEventHandleListener(
|
||||
type: DOMTopLevelEventType,
|
||||
capture: boolean,
|
||||
callback: (SyntheticEvent<EventTarget>) => void,
|
||||
destroy: (target: EventTarget | ReactScopeInstance) => void,
|
||||
): ReactDOMEventHandleListener {
|
||||
return {
|
||||
callback,
|
||||
capture,
|
||||
destroy,
|
||||
type,
|
||||
};
|
||||
}
|
||||
@@ -111,6 +111,65 @@ function registerEventOnNearestTargetContainer(
|
||||
);
|
||||
}
|
||||
|
||||
function registerReactDOMEvent(
|
||||
target: EventTarget | ReactScopeInstance,
|
||||
topLevelType: DOMTopLevelEventType,
|
||||
passive: boolean | void,
|
||||
capture: boolean,
|
||||
priority: EventPriority | void,
|
||||
): void {
|
||||
// Check if the target is a DOM element.
|
||||
if ((target: any).nodeType === ELEMENT_NODE) {
|
||||
const targetElement = ((target: any): Element);
|
||||
// Check if the DOM element is managed by React.
|
||||
const targetFiber = getClosestInstanceFromNode(targetElement);
|
||||
if (targetFiber === null) {
|
||||
invariant(
|
||||
false,
|
||||
'ReactDOM.createEventHandle: setListener called on an element ' +
|
||||
'target that is not managed by React. Ensure React rendered the DOM element.',
|
||||
);
|
||||
}
|
||||
registerEventOnNearestTargetContainer(
|
||||
targetFiber,
|
||||
topLevelType,
|
||||
passive,
|
||||
priority,
|
||||
);
|
||||
} else if (enableScopeAPI && isReactScope(target)) {
|
||||
const scopeTarget = ((target: any): ReactScopeInstance);
|
||||
const targetFiber = getFiberFromScopeInstance(scopeTarget);
|
||||
if (targetFiber === null) {
|
||||
// Scope is unmounted, do not proceed.
|
||||
return;
|
||||
}
|
||||
registerEventOnNearestTargetContainer(
|
||||
targetFiber,
|
||||
topLevelType,
|
||||
passive,
|
||||
priority,
|
||||
);
|
||||
} else if (isValidEventTarget(target)) {
|
||||
const eventTarget = ((target: any): EventTarget);
|
||||
const listenerMap = getEventListenerMap(eventTarget);
|
||||
listenToTopLevelEvent(
|
||||
topLevelType,
|
||||
eventTarget,
|
||||
listenerMap,
|
||||
PLUGIN_EVENT_SYSTEM | IS_TARGET_PHASE_ONLY,
|
||||
capture,
|
||||
passive,
|
||||
priority,
|
||||
);
|
||||
} else {
|
||||
invariant(
|
||||
false,
|
||||
'ReactDOM.createEventHandle: setter called on an invalid ' +
|
||||
'target. Provide a valid EventTarget or an element managed by React.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function createEventHandle(
|
||||
type: string,
|
||||
options?: EventHandleOptions,
|
||||
@@ -140,110 +199,39 @@ export function createEventHandle(
|
||||
priority = getEventPriorityForListenerSystem(topLevelType);
|
||||
}
|
||||
|
||||
const listeners = new Map();
|
||||
const registeredReactDOMEvents = new PossiblyWeakSet();
|
||||
|
||||
const destroy = (target: EventTarget | ReactScopeInstance): void => {
|
||||
const listener = listeners.get(target);
|
||||
if (listener !== undefined) {
|
||||
listeners.delete(target);
|
||||
const targetListeners = getEventHandlerListeners(target);
|
||||
if (targetListeners !== null) {
|
||||
targetListeners.delete(listener);
|
||||
}
|
||||
return (
|
||||
target: EventTarget | ReactScopeInstance,
|
||||
callback: (SyntheticEvent<EventTarget>) => void,
|
||||
) => {
|
||||
invariant(
|
||||
typeof callback === 'function',
|
||||
'ReactDOM.createEventHandle: setter called with an invalid ' +
|
||||
'callback. The callback must be a function.',
|
||||
);
|
||||
if (!registeredReactDOMEvents.has(target)) {
|
||||
registeredReactDOMEvents.add(target);
|
||||
registerReactDOMEvent(target, topLevelType, passive, capture, priority);
|
||||
// Add the event to our known event types list.
|
||||
addEventTypeToDispatchConfig(topLevelType);
|
||||
}
|
||||
};
|
||||
|
||||
const clear = (): void => {
|
||||
const eventTargetsArr = Array.from(listeners.keys());
|
||||
for (let i = 0; i < eventTargetsArr.length; i++) {
|
||||
destroy(eventTargetsArr[i]);
|
||||
const listener = createEventHandleListener(
|
||||
topLevelType,
|
||||
capture,
|
||||
callback,
|
||||
);
|
||||
let targetListeners = getEventHandlerListeners(target);
|
||||
if (targetListeners === null) {
|
||||
targetListeners = new Set();
|
||||
setEventHandlerListeners(target, targetListeners);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
setListener(
|
||||
target: EventTarget | ReactScopeInstance,
|
||||
callback: null | ((SyntheticEvent<EventTarget>) => void),
|
||||
): void {
|
||||
// Check if the target is a DOM element.
|
||||
if ((target: any).nodeType === ELEMENT_NODE) {
|
||||
const targetElement = ((target: any): Element);
|
||||
// Check if the DOM element is managed by React.
|
||||
const targetFiber = getClosestInstanceFromNode(targetElement);
|
||||
if (targetFiber === null) {
|
||||
invariant(
|
||||
false,
|
||||
'ReactDOM.createEventHandle: setListener called on an element ' +
|
||||
'target that is not managed by React. Ensure React rendered the DOM element.',
|
||||
);
|
||||
}
|
||||
registerEventOnNearestTargetContainer(
|
||||
targetFiber,
|
||||
topLevelType,
|
||||
passive,
|
||||
priority,
|
||||
);
|
||||
} else if (enableScopeAPI && isReactScope(target)) {
|
||||
const scopeTarget = ((target: any): ReactScopeInstance);
|
||||
const targetFiber = getFiberFromScopeInstance(scopeTarget);
|
||||
if (targetFiber === null) {
|
||||
// Scope is unmounted, do not proceed.
|
||||
return;
|
||||
}
|
||||
registerEventOnNearestTargetContainer(
|
||||
targetFiber,
|
||||
topLevelType,
|
||||
passive,
|
||||
priority,
|
||||
);
|
||||
} else if (isValidEventTarget(target)) {
|
||||
const eventTarget = ((target: any): EventTarget);
|
||||
const listenerMap = getEventListenerMap(eventTarget);
|
||||
listenToTopLevelEvent(
|
||||
topLevelType,
|
||||
eventTarget,
|
||||
listenerMap,
|
||||
PLUGIN_EVENT_SYSTEM | IS_TARGET_PHASE_ONLY,
|
||||
capture,
|
||||
passive,
|
||||
priority,
|
||||
);
|
||||
} else {
|
||||
invariant(
|
||||
false,
|
||||
'ReactDOM.createEventHandle: setListener called on an invalid ' +
|
||||
'target. Provide a valid EventTarget or an element managed by React.',
|
||||
);
|
||||
}
|
||||
let listener = listeners.get(target);
|
||||
if (listener === undefined) {
|
||||
if (callback === null) {
|
||||
return;
|
||||
}
|
||||
listener = createEventHandleListener(
|
||||
topLevelType,
|
||||
capture,
|
||||
callback,
|
||||
destroy,
|
||||
);
|
||||
listeners.set(target, listener);
|
||||
|
||||
let targetListeners = getEventHandlerListeners(target);
|
||||
if (targetListeners === null) {
|
||||
targetListeners = new Set();
|
||||
setEventHandlerListeners(target, targetListeners);
|
||||
}
|
||||
targetListeners.add(listener);
|
||||
// Finally, add the event to our known event types list.
|
||||
addEventTypeToDispatchConfig(topLevelType);
|
||||
} else if (callback !== null) {
|
||||
listener.callback = callback;
|
||||
} else {
|
||||
// Remove listener
|
||||
destroy(target);
|
||||
}
|
||||
},
|
||||
clear,
|
||||
targetListeners.add(listener);
|
||||
return () => {
|
||||
((targetListeners: any): Set<ReactDOMEventHandleListener>).delete(
|
||||
listener,
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
return (null: any);
|
||||
|
||||
@@ -80,10 +80,7 @@ import {
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import {HostComponent, HostText} from 'react-reconciler/src/ReactWorkTags';
|
||||
import {TOP_BEFORE_BLUR, TOP_AFTER_BLUR} from '../events/DOMTopLevelEventTypes';
|
||||
import {
|
||||
listenToReactPropEvent,
|
||||
clearEventHandleListenersForTarget,
|
||||
} from '../events/DOMModernPluginEventSystem';
|
||||
import {listenToReactPropEvent} from '../events/DOMModernPluginEventSystem';
|
||||
|
||||
export type Type = string;
|
||||
export type Props = {
|
||||
@@ -534,14 +531,6 @@ function dispatchAfterDetachedBlur(target: HTMLElement): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function removeInstanceEventHandles(
|
||||
instance: Instance | TextInstance | SuspenseInstance,
|
||||
) {
|
||||
if (enableCreateEventHandleAPI) {
|
||||
clearEventHandleListenersForTarget(instance);
|
||||
}
|
||||
}
|
||||
|
||||
export function removeChild(
|
||||
parentInstance: Instance,
|
||||
child: Instance | TextInstance | SuspenseInstance,
|
||||
@@ -1134,14 +1123,6 @@ export function prepareScopeUpdate(
|
||||
}
|
||||
}
|
||||
|
||||
export function removeScopeEventHandles(
|
||||
scopeInstance: ReactScopeInstance,
|
||||
): void {
|
||||
if (enableScopeAPI && enableCreateEventHandleAPI) {
|
||||
clearEventHandleListenersForTarget(scopeInstance);
|
||||
}
|
||||
}
|
||||
|
||||
export function getInstanceFromScope(
|
||||
scopeInstance: ReactScopeInstance,
|
||||
): null | Object {
|
||||
|
||||
@@ -21,7 +21,7 @@ import type {
|
||||
ElementListenerMap,
|
||||
ElementListenerMapEntry,
|
||||
} from '../client/ReactDOMComponentTree';
|
||||
import type {EventPriority, ReactScopeInstance} from 'shared/ReactTypes';
|
||||
import type {EventPriority} from 'shared/ReactTypes';
|
||||
import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
|
||||
|
||||
import {registrationNameDependencies} from './EventRegistry';
|
||||
@@ -954,24 +954,6 @@ export function addEventTypeToDispatchConfig(type: DOMTopLevelEventType): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function clearEventHandleListenersForTarget(
|
||||
target: EventTarget | ReactScopeInstance,
|
||||
): void {
|
||||
// It's unfortunate that we have to do this cleanup, but
|
||||
// it's necessary otherwise we will leak the host instances
|
||||
// on the createEventHandle API "listeners" Map. We call destroy
|
||||
// on each listener to ensure we properly remove the instance
|
||||
// from the listeners Map. Note: we have this Map so that we
|
||||
// can track listeners for the handle.clear() API call.
|
||||
const listeners = getEventHandlerListeners(target);
|
||||
if (listeners !== null) {
|
||||
const listenersArr = Array.from(listeners);
|
||||
for (let i = 0; i < listenersArr.length; i++) {
|
||||
listenersArr[i].destroy(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getListenerMapKey(
|
||||
topLevelType: DOMTopLevelEventType,
|
||||
capture: boolean,
|
||||
|
||||
@@ -1208,13 +1208,13 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
// @gate experimental
|
||||
it('can render correctly with the ReactDOMServer', () => {
|
||||
const clickEvent = jest.fn();
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test() {
|
||||
const divRef = React.useRef(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
click.setListener(divRef.current, clickEvent);
|
||||
return setClick(divRef.current, clickEvent);
|
||||
});
|
||||
|
||||
return <div ref={divRef}>Hello world</div>;
|
||||
@@ -1227,11 +1227,11 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
it('can render correctly with the ReactDOMServer hydration', () => {
|
||||
const clickEvent = jest.fn();
|
||||
const spanRef = React.createRef();
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test() {
|
||||
React.useEffect(() => {
|
||||
click.setListener(spanRef.current, clickEvent);
|
||||
return setClick(spanRef.current, clickEvent);
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -1264,11 +1264,11 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
});
|
||||
const divRef = React.createRef();
|
||||
const buttonRef = React.createRef();
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test() {
|
||||
React.useEffect(() => {
|
||||
click.setListener(buttonRef.current, clickEvent);
|
||||
return setClick(buttonRef.current, clickEvent);
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -1327,11 +1327,11 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const click2 = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick2 = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test2({clickEvent2}) {
|
||||
React.useEffect(() => {
|
||||
click2.setListener(buttonRef.current, clickEvent2);
|
||||
return setClick2(buttonRef.current, clickEvent2);
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -1364,18 +1364,16 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const clickEvent = jest.fn();
|
||||
const divRef = React.createRef();
|
||||
const buttonRef = React.createRef();
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test({off}) {
|
||||
React.useEffect(() => {
|
||||
click.setListener(buttonRef.current, clickEvent);
|
||||
});
|
||||
|
||||
React.useEffect(() => {
|
||||
const clear = setClick(buttonRef.current, clickEvent);
|
||||
if (off) {
|
||||
click.setListener(buttonRef.current, null);
|
||||
clear();
|
||||
}
|
||||
}, [off]);
|
||||
return clear;
|
||||
});
|
||||
|
||||
return (
|
||||
<button ref={buttonRef}>
|
||||
@@ -1391,7 +1389,7 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
dispatchClickEvent(divElement);
|
||||
expect(clickEvent).toBeCalledTimes(1);
|
||||
|
||||
// The listener should get unmounted in the second effect
|
||||
// The listener should get unmounted
|
||||
ReactDOM.render(<Test off={true} />, container);
|
||||
Scheduler.unstable_flushAll();
|
||||
|
||||
@@ -1406,11 +1404,11 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
it('should handle the target being a text node', () => {
|
||||
const clickEvent = jest.fn();
|
||||
const buttonRef = React.createRef();
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test() {
|
||||
React.useEffect(() => {
|
||||
click.setListener(buttonRef.current, clickEvent);
|
||||
return setClick(buttonRef.current, clickEvent);
|
||||
});
|
||||
|
||||
return <button ref={buttonRef}>Click me!</button>;
|
||||
@@ -1433,17 +1431,33 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const onClickCapture = jest.fn(e =>
|
||||
log.push(['capture', e.currentTarget]),
|
||||
);
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const clickCapture = ReactDOM.unstable_createEventHandle('click', {
|
||||
capture: true,
|
||||
});
|
||||
const setClick = ReactDOM.unstable_createEventHandle('click');
|
||||
const setCaptureClick = ReactDOM.unstable_createEventHandle(
|
||||
'click',
|
||||
{
|
||||
capture: true,
|
||||
},
|
||||
);
|
||||
|
||||
function Test() {
|
||||
React.useEffect(() => {
|
||||
click.setListener(buttonRef.current, onClick);
|
||||
clickCapture.setListener(buttonRef.current, onClickCapture);
|
||||
click.setListener(divRef.current, onClick);
|
||||
clickCapture.setListener(divRef.current, onClickCapture);
|
||||
const clearClick1 = setClick(buttonRef.current, onClick);
|
||||
const clearCaptureClick1 = setCaptureClick(
|
||||
buttonRef.current,
|
||||
onClickCapture,
|
||||
);
|
||||
const clearClick2 = setClick(divRef.current, onClick);
|
||||
const clearCaptureClick2 = setCaptureClick(
|
||||
divRef.current,
|
||||
onClickCapture,
|
||||
);
|
||||
|
||||
return () => {
|
||||
clearClick1();
|
||||
clearCaptureClick1();
|
||||
clearClick2();
|
||||
clearCaptureClick2();
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -1486,15 +1500,23 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const onClickCapture = jest.fn(e =>
|
||||
log.push(['capture', e.currentTarget]),
|
||||
);
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const clickCapture = ReactDOM.unstable_createEventHandle('click', {
|
||||
capture: true,
|
||||
});
|
||||
const setClick = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClickCapture = ReactDOM.unstable_createEventHandle(
|
||||
'click',
|
||||
{
|
||||
capture: true,
|
||||
},
|
||||
);
|
||||
|
||||
function Test() {
|
||||
React.useEffect(() => {
|
||||
click.setListener(buttonRef.current, onClick);
|
||||
clickCapture.setListener(buttonRef.current, onClickCapture);
|
||||
setClick(buttonRef.current, onClick);
|
||||
setClickCapture(buttonRef.current, onClickCapture);
|
||||
|
||||
return () => {
|
||||
setClick();
|
||||
setClickCapture();
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -1542,11 +1564,11 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
});
|
||||
const divRef = React.createRef();
|
||||
const buttonRef = React.createRef();
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test() {
|
||||
React.useEffect(() => {
|
||||
click.setListener(divRef.current, clickEvent);
|
||||
return setClick(divRef.current, clickEvent);
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -1601,21 +1623,28 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const targetListener2 = jest.fn();
|
||||
const targetListener3 = jest.fn();
|
||||
const targetListener4 = jest.fn();
|
||||
let click1 = ReactDOM.unstable_createEventHandle('click', {
|
||||
let setClick1 = ReactDOM.unstable_createEventHandle('click', {
|
||||
capture: true,
|
||||
});
|
||||
let click2 = ReactDOM.unstable_createEventHandle('click', {
|
||||
let setClick2 = ReactDOM.unstable_createEventHandle('click', {
|
||||
capture: true,
|
||||
});
|
||||
let click3 = ReactDOM.unstable_createEventHandle('click');
|
||||
let click4 = ReactDOM.unstable_createEventHandle('click');
|
||||
let setClick3 = ReactDOM.unstable_createEventHandle('click');
|
||||
let setClick4 = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test() {
|
||||
React.useEffect(() => {
|
||||
click1.setListener(buttonRef.current, targetListener1);
|
||||
click2.setListener(buttonRef.current, targetListener2);
|
||||
click3.setListener(buttonRef.current, targetListener3);
|
||||
click4.setListener(buttonRef.current, targetListener4);
|
||||
setClick1(buttonRef.current, targetListener1);
|
||||
setClick2(buttonRef.current, targetListener2);
|
||||
setClick3(buttonRef.current, targetListener3);
|
||||
setClick4(buttonRef.current, targetListener4);
|
||||
|
||||
return () => {
|
||||
setClick1();
|
||||
setClick2();
|
||||
setClick3();
|
||||
setClick4();
|
||||
};
|
||||
});
|
||||
|
||||
return <button ref={buttonRef}>Click me!</button>;
|
||||
@@ -1632,17 +1661,24 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
expect(targetListener3).toHaveBeenCalledTimes(1);
|
||||
expect(targetListener4).toHaveBeenCalledTimes(1);
|
||||
|
||||
click1 = ReactDOM.unstable_createEventHandle('click');
|
||||
click2 = ReactDOM.unstable_createEventHandle('click');
|
||||
click3 = ReactDOM.unstable_createEventHandle('click');
|
||||
click4 = ReactDOM.unstable_createEventHandle('click');
|
||||
setClick1 = ReactDOM.unstable_createEventHandle('click');
|
||||
setClick2 = ReactDOM.unstable_createEventHandle('click');
|
||||
setClick3 = ReactDOM.unstable_createEventHandle('click');
|
||||
setClick4 = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test2() {
|
||||
React.useEffect(() => {
|
||||
click1.setListener(buttonRef.current, targetListener1);
|
||||
click2.setListener(buttonRef.current, targetListener2);
|
||||
click3.setListener(buttonRef.current, targetListener3);
|
||||
click4.setListener(buttonRef.current, targetListener4);
|
||||
setClick1(buttonRef.current, targetListener1);
|
||||
setClick2(buttonRef.current, targetListener2);
|
||||
setClick3(buttonRef.current, targetListener3);
|
||||
setClick4(buttonRef.current, targetListener4);
|
||||
|
||||
return () => {
|
||||
setClick1();
|
||||
setClick2();
|
||||
setClick3();
|
||||
setClick4();
|
||||
};
|
||||
});
|
||||
|
||||
return <button ref={buttonRef}>Click me!</button>;
|
||||
@@ -1664,17 +1700,22 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const buttonRef = React.createRef();
|
||||
const divRef = React.createRef();
|
||||
const clickEvent = jest.fn();
|
||||
const click1 = ReactDOM.unstable_createEventHandle('click', {
|
||||
const setClick1 = ReactDOM.unstable_createEventHandle('click', {
|
||||
bind: buttonRef,
|
||||
});
|
||||
const click2 = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick2 = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test() {
|
||||
React.useEffect(() => {
|
||||
click1.setListener(buttonRef.current, clickEvent);
|
||||
click2.setListener(divRef.current, e => {
|
||||
const clearClick1 = setClick1(buttonRef.current, clickEvent);
|
||||
const clearClick2 = setClick2(divRef.current, e => {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
return () => {
|
||||
clearClick1();
|
||||
clearClick2();
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -1699,17 +1740,36 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const targetListener2 = jest.fn(e => e.stopPropagation());
|
||||
const targetListener3 = jest.fn(e => e.stopPropagation());
|
||||
const targetListener4 = jest.fn(e => e.stopPropagation());
|
||||
const click1 = ReactDOM.unstable_createEventHandle('click');
|
||||
const click2 = ReactDOM.unstable_createEventHandle('click');
|
||||
const click3 = ReactDOM.unstable_createEventHandle('click');
|
||||
const click4 = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick1 = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick2 = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick3 = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick4 = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test() {
|
||||
React.useEffect(() => {
|
||||
click1.setListener(buttonRef.current, targetListener1);
|
||||
click2.setListener(buttonRef.current, targetListener2);
|
||||
click3.setListener(buttonRef.current, targetListener3);
|
||||
click4.setListener(buttonRef.current, targetListener4);
|
||||
const clearClick1 = setClick1(
|
||||
buttonRef.current,
|
||||
targetListener1,
|
||||
);
|
||||
const clearClick2 = setClick2(
|
||||
buttonRef.current,
|
||||
targetListener2,
|
||||
);
|
||||
const clearClick3 = setClick3(
|
||||
buttonRef.current,
|
||||
targetListener3,
|
||||
);
|
||||
const clearClick4 = setClick4(
|
||||
buttonRef.current,
|
||||
targetListener4,
|
||||
);
|
||||
|
||||
return () => {
|
||||
clearClick1();
|
||||
clearClick2();
|
||||
clearClick3();
|
||||
clearClick4();
|
||||
};
|
||||
});
|
||||
|
||||
return <button ref={buttonRef}>Click me!</button>;
|
||||
@@ -1733,21 +1793,40 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const targetListener2 = jest.fn(e => e.stopPropagation());
|
||||
const targetListener3 = jest.fn(e => e.stopPropagation());
|
||||
const targetListener4 = jest.fn(e => e.stopPropagation());
|
||||
const click1 = ReactDOM.unstable_createEventHandle('click', {
|
||||
const setClick1 = ReactDOM.unstable_createEventHandle('click', {
|
||||
capture: true,
|
||||
});
|
||||
const click2 = ReactDOM.unstable_createEventHandle('click', {
|
||||
const setClick2 = ReactDOM.unstable_createEventHandle('click', {
|
||||
capture: true,
|
||||
});
|
||||
const click3 = ReactDOM.unstable_createEventHandle('click');
|
||||
const click4 = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick3 = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick4 = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test() {
|
||||
React.useEffect(() => {
|
||||
click1.setListener(buttonRef.current, targetListener1);
|
||||
click2.setListener(buttonRef.current, targetListener2);
|
||||
click3.setListener(buttonRef.current, targetListener3);
|
||||
click4.setListener(buttonRef.current, targetListener4);
|
||||
const clearClick1 = setClick1(
|
||||
buttonRef.current,
|
||||
targetListener1,
|
||||
);
|
||||
const clearClick2 = setClick2(
|
||||
buttonRef.current,
|
||||
targetListener2,
|
||||
);
|
||||
const clearClick3 = setClick3(
|
||||
buttonRef.current,
|
||||
targetListener3,
|
||||
);
|
||||
const clearClick4 = setClick4(
|
||||
buttonRef.current,
|
||||
targetListener4,
|
||||
);
|
||||
|
||||
return () => {
|
||||
clearClick1();
|
||||
clearClick2();
|
||||
clearClick3();
|
||||
clearClick4();
|
||||
};
|
||||
});
|
||||
|
||||
return <button ref={buttonRef}>Click me!</button>;
|
||||
@@ -1768,11 +1847,11 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
it('should work with concurrent mode updates', async () => {
|
||||
const log = [];
|
||||
const ref = React.createRef();
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick1 = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test({counter}) {
|
||||
React.useLayoutEffect(() => {
|
||||
click.setListener(ref.current, () => {
|
||||
return setClick1(ref.current, () => {
|
||||
log.push({counter});
|
||||
});
|
||||
});
|
||||
@@ -1816,16 +1895,16 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const clickEvent = jest.fn();
|
||||
const buttonRef = React.createRef();
|
||||
const button2Ref = React.createRef();
|
||||
const click = ReactDOM.unstable_createEventHandle('click', {
|
||||
const setClick1 = ReactDOM.unstable_createEventHandle('click', {
|
||||
passive: false,
|
||||
});
|
||||
const click2 = ReactDOM.unstable_createEventHandle('click', {
|
||||
const setClick2 = ReactDOM.unstable_createEventHandle('click', {
|
||||
passive: true,
|
||||
});
|
||||
|
||||
function Test2() {
|
||||
React.useEffect(() => {
|
||||
click.setListener(button2Ref.current, clickEvent);
|
||||
return setClick1(button2Ref.current, clickEvent);
|
||||
});
|
||||
|
||||
return <button ref={button2Ref}>Click me!</button>;
|
||||
@@ -1833,7 +1912,7 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
|
||||
function Test({extra}) {
|
||||
React.useEffect(() => {
|
||||
click2.setListener(buttonRef.current, clickEvent);
|
||||
return setClick2(buttonRef.current, clickEvent);
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -1866,16 +1945,16 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const clickEvent = jest.fn();
|
||||
const buttonRef = React.createRef();
|
||||
const button2Ref = React.createRef();
|
||||
const click = ReactDOM.unstable_createEventHandle('click', {
|
||||
const setClick1 = ReactDOM.unstable_createEventHandle('click', {
|
||||
passive: false,
|
||||
});
|
||||
const click2 = ReactDOM.unstable_createEventHandle('click', {
|
||||
const setClick2 = ReactDOM.unstable_createEventHandle('click', {
|
||||
passive: undefined,
|
||||
});
|
||||
|
||||
function Test2() {
|
||||
React.useEffect(() => {
|
||||
click.setListener(button2Ref.current, clickEvent);
|
||||
return setClick1(button2Ref.current, clickEvent);
|
||||
});
|
||||
|
||||
return <button ref={button2Ref}>Click me!</button>;
|
||||
@@ -1883,7 +1962,7 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
|
||||
function Test({extra}) {
|
||||
React.useEffect(() => {
|
||||
click2.setListener(buttonRef.current, clickEvent);
|
||||
return setClick2(buttonRef.current, clickEvent);
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -1922,15 +2001,11 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
target: event.target,
|
||||
});
|
||||
});
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick1 = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test() {
|
||||
React.useEffect(() => {
|
||||
click.setListener(window, clickEvent);
|
||||
|
||||
return () => {
|
||||
click.setListener(window, null);
|
||||
};
|
||||
return setClick1(window, clickEvent);
|
||||
});
|
||||
|
||||
return <button>Click anything!</button>;
|
||||
@@ -1975,23 +2050,39 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const onClickCapture = jest.fn(e =>
|
||||
log.push(['capture', e.currentTarget]),
|
||||
);
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const clickCapture = ReactDOM.unstable_createEventHandle('click', {
|
||||
capture: true,
|
||||
});
|
||||
const setClick = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClickCapture = ReactDOM.unstable_createEventHandle(
|
||||
'click',
|
||||
{
|
||||
capture: true,
|
||||
},
|
||||
);
|
||||
|
||||
function Test() {
|
||||
React.useEffect(() => {
|
||||
click.setListener(window, onClick);
|
||||
clickCapture.setListener(window, onClickCapture);
|
||||
click.setListener(buttonRef.current, onClick);
|
||||
clickCapture.setListener(buttonRef.current, onClickCapture);
|
||||
click.setListener(divRef.current, onClick);
|
||||
clickCapture.setListener(divRef.current, onClickCapture);
|
||||
const clearClick1 = setClick(window, onClick);
|
||||
const clearClickCapture1 = setClickCapture(
|
||||
window,
|
||||
onClickCapture,
|
||||
);
|
||||
const clearClick2 = setClick(buttonRef.current, onClick);
|
||||
const clearClickCapture2 = setClickCapture(
|
||||
buttonRef.current,
|
||||
onClickCapture,
|
||||
);
|
||||
const clearClick3 = setClick(divRef.current, onClick);
|
||||
const clearClickCapture3 = setClickCapture(
|
||||
divRef.current,
|
||||
onClickCapture,
|
||||
);
|
||||
|
||||
return () => {
|
||||
click.setListener(window, null);
|
||||
clickCapture.setListener(window, null);
|
||||
clearClick1();
|
||||
clearClickCapture1();
|
||||
clearClick2();
|
||||
clearClickCapture2();
|
||||
clearClick3();
|
||||
clearClickCapture3();
|
||||
};
|
||||
});
|
||||
|
||||
@@ -2037,25 +2128,33 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const rootListener2 = jest.fn();
|
||||
const targetListener1 = jest.fn();
|
||||
const targetListener2 = jest.fn();
|
||||
const click1 = ReactDOM.unstable_createEventHandle('click', {
|
||||
const setClick1 = ReactDOM.unstable_createEventHandle('click', {
|
||||
capture: true,
|
||||
});
|
||||
const click2 = ReactDOM.unstable_createEventHandle('click', {
|
||||
const setClick2 = ReactDOM.unstable_createEventHandle('click', {
|
||||
capture: true,
|
||||
});
|
||||
const click3 = ReactDOM.unstable_createEventHandle('click');
|
||||
const click4 = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick3 = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick4 = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test() {
|
||||
React.useEffect(() => {
|
||||
click1.setListener(window, rootListener1);
|
||||
click2.setListener(buttonRef.current, targetListener1);
|
||||
click3.setListener(window, rootListener2);
|
||||
click4.setListener(buttonRef.current, targetListener2);
|
||||
const clearClick1 = setClick1(window, rootListener1);
|
||||
const clearClick2 = setClick2(
|
||||
buttonRef.current,
|
||||
targetListener1,
|
||||
);
|
||||
const clearClick3 = setClick3(window, rootListener2);
|
||||
const clearClick4 = setClick4(
|
||||
buttonRef.current,
|
||||
targetListener2,
|
||||
);
|
||||
|
||||
return () => {
|
||||
click1.setListener(window, null);
|
||||
click3.setListener(window, null);
|
||||
clearClick1();
|
||||
clearClick2();
|
||||
clearClick3();
|
||||
clearClick4();
|
||||
};
|
||||
});
|
||||
|
||||
@@ -2080,27 +2179,27 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const rootListener2 = jest.fn();
|
||||
const rootListener3 = jest.fn(e => e.stopPropagation());
|
||||
const rootListener4 = jest.fn();
|
||||
const click1 = ReactDOM.unstable_createEventHandle('click', {
|
||||
const setClick1 = ReactDOM.unstable_createEventHandle('click', {
|
||||
capture: true,
|
||||
});
|
||||
const click2 = ReactDOM.unstable_createEventHandle('click', {
|
||||
const setClick2 = ReactDOM.unstable_createEventHandle('click', {
|
||||
capture: true,
|
||||
});
|
||||
const click3 = ReactDOM.unstable_createEventHandle('click');
|
||||
const click4 = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick3 = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick4 = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test() {
|
||||
React.useEffect(() => {
|
||||
click1.setListener(window, rootListener1);
|
||||
click2.setListener(window, rootListener2);
|
||||
click3.setListener(window, rootListener3);
|
||||
click4.setListener(window, rootListener4);
|
||||
const clearClick1 = setClick1(window, rootListener1);
|
||||
const clearClick2 = setClick2(window, rootListener2);
|
||||
const clearClick3 = setClick3(window, rootListener3);
|
||||
const clearClick4 = setClick4(window, rootListener4);
|
||||
|
||||
return () => {
|
||||
click1.setListener(window, null);
|
||||
click2.setListener(window, null);
|
||||
click3.setListener(window, null);
|
||||
click4.setListener(window, null);
|
||||
clearClick1();
|
||||
clearClick2();
|
||||
clearClick3();
|
||||
clearClick4();
|
||||
};
|
||||
});
|
||||
|
||||
@@ -2128,27 +2227,46 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const onClickCapture = jest.fn(e =>
|
||||
log.push(['capture', e.currentTarget]),
|
||||
);
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const clickCapture = ReactDOM.unstable_createEventHandle('click', {
|
||||
capture: true,
|
||||
});
|
||||
const setClick = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClickCapture = ReactDOM.unstable_createEventHandle(
|
||||
'click',
|
||||
{
|
||||
capture: true,
|
||||
},
|
||||
);
|
||||
|
||||
function Test() {
|
||||
React.useEffect(() => {
|
||||
click.setListener(window, onClick);
|
||||
clickCapture.setListener(window, onClickCapture);
|
||||
click.setListener(document, onClick);
|
||||
clickCapture.setListener(document, onClickCapture);
|
||||
click.setListener(buttonRef.current, onClick);
|
||||
clickCapture.setListener(buttonRef.current, onClickCapture);
|
||||
click.setListener(divRef.current, onClick);
|
||||
clickCapture.setListener(divRef.current, onClickCapture);
|
||||
const clearClick1 = setClick(window, onClick);
|
||||
const clearClickCapture1 = setClickCapture(
|
||||
window,
|
||||
onClickCapture,
|
||||
);
|
||||
const clearClick2 = setClick(document, onClick);
|
||||
const clearClickCapture2 = setClickCapture(
|
||||
document,
|
||||
onClickCapture,
|
||||
);
|
||||
const clearClick3 = setClick(buttonRef.current, onClick);
|
||||
const clearClickCapture3 = setClickCapture(
|
||||
buttonRef.current,
|
||||
onClickCapture,
|
||||
);
|
||||
const clearClick4 = setClick(divRef.current, onClick);
|
||||
const clearClickCapture4 = setClickCapture(
|
||||
divRef.current,
|
||||
onClickCapture,
|
||||
);
|
||||
|
||||
return () => {
|
||||
click.setListener(window, null);
|
||||
clickCapture.setListener(window, null);
|
||||
click.setListener(document, null);
|
||||
clickCapture.setListener(document, null);
|
||||
clearClick1();
|
||||
clearClickCapture1();
|
||||
clearClick2();
|
||||
clearClickCapture2();
|
||||
clearClick3();
|
||||
clearClickCapture3();
|
||||
clearClick4();
|
||||
clearClickCapture4();
|
||||
};
|
||||
});
|
||||
|
||||
@@ -2225,11 +2343,11 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
log.push(['capture', e.currentTarget]),
|
||||
);
|
||||
|
||||
let customEventHandle;
|
||||
let setCustomEventHandle;
|
||||
|
||||
// Test that we get a warning when we don't provide an explicit priority
|
||||
expect(() => {
|
||||
customEventHandle = ReactDOM.unstable_createEventHandle(
|
||||
setCustomEventHandle = ReactDOM.unstable_createEventHandle(
|
||||
'custom-event',
|
||||
);
|
||||
}).toWarnDev(
|
||||
@@ -2238,14 +2356,14 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
{withoutStack: true},
|
||||
);
|
||||
|
||||
customEventHandle = ReactDOM.unstable_createEventHandle(
|
||||
setCustomEventHandle = ReactDOM.unstable_createEventHandle(
|
||||
'custom-event',
|
||||
{
|
||||
priority: 0, // Discrete
|
||||
},
|
||||
);
|
||||
|
||||
const customCaptureHandle = ReactDOM.unstable_createEventHandle(
|
||||
const setCustomCaptureHandle = ReactDOM.unstable_createEventHandle(
|
||||
'custom-event',
|
||||
{
|
||||
capture: true,
|
||||
@@ -2255,16 +2373,29 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
|
||||
function Test() {
|
||||
React.useEffect(() => {
|
||||
customEventHandle.setListener(buttonRef.current, onCustomEvent);
|
||||
customCaptureHandle.setListener(
|
||||
const clearCustom1 = setCustomEventHandle(
|
||||
buttonRef.current,
|
||||
onCustomEvent,
|
||||
);
|
||||
const clearCustom2 = setCustomCaptureHandle(
|
||||
buttonRef.current,
|
||||
onCustomEventCapture,
|
||||
);
|
||||
customEventHandle.setListener(divRef.current, onCustomEvent);
|
||||
customCaptureHandle.setListener(
|
||||
const clearCustom3 = setCustomEventHandle(
|
||||
divRef.current,
|
||||
onCustomEvent,
|
||||
);
|
||||
const clearCustom4 = setCustomCaptureHandle(
|
||||
divRef.current,
|
||||
onCustomEventCapture,
|
||||
);
|
||||
|
||||
return () => {
|
||||
clearCustom1();
|
||||
clearCustom2();
|
||||
clearCustom3();
|
||||
clearCustom4();
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -2305,10 +2436,10 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const onBeforeBlur = jest.fn(e => log.push(e.type));
|
||||
const innerRef = React.createRef();
|
||||
const innerRef2 = React.createRef();
|
||||
const afterBlurHandle = ReactDOM.unstable_createEventHandle(
|
||||
const setAfterBlurHandle = ReactDOM.unstable_createEventHandle(
|
||||
'afterblur',
|
||||
);
|
||||
const beforeBlurHandle = ReactDOM.unstable_createEventHandle(
|
||||
const setBeforeBlurHandle = ReactDOM.unstable_createEventHandle(
|
||||
'beforeblur',
|
||||
);
|
||||
|
||||
@@ -2316,8 +2447,13 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const ref = React.useRef(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
afterBlurHandle.setListener(document, onAfterBlur);
|
||||
beforeBlurHandle.setListener(ref.current, onBeforeBlur);
|
||||
const clear1 = setAfterBlurHandle(document, onAfterBlur);
|
||||
const clear2 = setBeforeBlurHandle(ref.current, onBeforeBlur);
|
||||
|
||||
return () => {
|
||||
clear1();
|
||||
clear2();
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -2359,10 +2495,10 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const onBeforeBlur = jest.fn(e => log.push(e.type));
|
||||
const innerRef = React.createRef();
|
||||
const innerRef2 = React.createRef();
|
||||
const afterBlurHandle = ReactDOM.unstable_createEventHandle(
|
||||
const setAfterBlurHandle = ReactDOM.unstable_createEventHandle(
|
||||
'afterblur',
|
||||
);
|
||||
const beforeBlurHandle = ReactDOM.unstable_createEventHandle(
|
||||
const setBeforeBlurHandle = ReactDOM.unstable_createEventHandle(
|
||||
'beforeblur',
|
||||
);
|
||||
|
||||
@@ -2370,8 +2506,13 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const ref = React.useRef(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
afterBlurHandle.setListener(document, onAfterBlur);
|
||||
beforeBlurHandle.setListener(ref.current, onBeforeBlur);
|
||||
const clear1 = setAfterBlurHandle(document, onAfterBlur);
|
||||
const clear2 = setBeforeBlurHandle(ref.current, onBeforeBlur);
|
||||
|
||||
return () => {
|
||||
clear1();
|
||||
clear2();
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -2422,10 +2563,10 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const promise = new Promise(
|
||||
resolvePromise => (resolve = resolvePromise),
|
||||
);
|
||||
const afterBlurHandle = ReactDOM.unstable_createEventHandle(
|
||||
const setAfterBlurHandle = ReactDOM.unstable_createEventHandle(
|
||||
'afterblur',
|
||||
);
|
||||
const beforeBlurHandle = ReactDOM.unstable_createEventHandle(
|
||||
const setBeforeBlurHandle = ReactDOM.unstable_createEventHandle(
|
||||
'beforeblur',
|
||||
);
|
||||
|
||||
@@ -2441,8 +2582,13 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const ref = React.useRef(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
afterBlurHandle.setListener(document, onAfterBlur);
|
||||
beforeBlurHandle.setListener(ref.current, onBeforeBlur);
|
||||
const clear1 = setAfterBlurHandle(document, onAfterBlur);
|
||||
const clear2 = setBeforeBlurHandle(ref.current, onBeforeBlur);
|
||||
|
||||
return () => {
|
||||
clear1();
|
||||
clear2();
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -2492,7 +2638,7 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const Suspense = React.Suspense;
|
||||
let suspend = false;
|
||||
const promise = Promise.resolve();
|
||||
const beforeBlurHandle = ReactDOM.unstable_createEventHandle(
|
||||
const setBeforeBlurHandle = ReactDOM.unstable_createEventHandle(
|
||||
'beforeblur',
|
||||
);
|
||||
const innerRef = React.createRef();
|
||||
@@ -2509,7 +2655,7 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const [, setState] = React.useState(0);
|
||||
|
||||
React.useEffect(() => {
|
||||
beforeBlurHandle.setListener(ref.current, () => {
|
||||
return setBeforeBlurHandle(ref.current, () => {
|
||||
// In the regression case, this would trigger an update, then
|
||||
// the resulting render would trigger another blur event,
|
||||
// which would trigger an update again, and on and on in an
|
||||
@@ -2573,8 +2719,8 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
log.push(['capture', e.currentTarget]),
|
||||
);
|
||||
const TestScope = React.unstable_createScope();
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const clickCapture = ReactDOM.unstable_createEventHandle(
|
||||
const setClick = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClickCapture = ReactDOM.unstable_createEventHandle(
|
||||
'click',
|
||||
{
|
||||
capture: true,
|
||||
@@ -2585,8 +2731,16 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const scopeRef = React.useRef(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
click.setListener(scopeRef.current, onClick);
|
||||
clickCapture.setListener(scopeRef.current, onClickCapture);
|
||||
const clear1 = setClick(scopeRef.current, onClick);
|
||||
const clear2 = setClickCapture(
|
||||
scopeRef.current,
|
||||
onClickCapture,
|
||||
);
|
||||
|
||||
return () => {
|
||||
clear1();
|
||||
clear2();
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -2622,8 +2776,8 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
log.push(['capture', e.currentTarget]),
|
||||
);
|
||||
const TestScope = React.unstable_createScope();
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const clickCapture = ReactDOM.unstable_createEventHandle(
|
||||
const setClick = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClickCapture = ReactDOM.unstable_createEventHandle(
|
||||
'click',
|
||||
{
|
||||
capture: true,
|
||||
@@ -2634,10 +2788,23 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const scopeRef = React.useRef(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
click.setListener(scopeRef.current, onClick);
|
||||
clickCapture.setListener(scopeRef.current, onClickCapture);
|
||||
click.setListener(buttonRef.current, onClick);
|
||||
clickCapture.setListener(buttonRef.current, onClickCapture);
|
||||
const clear1 = setClick(scopeRef.current, onClick);
|
||||
const clear2 = setClickCapture(
|
||||
scopeRef.current,
|
||||
onClickCapture,
|
||||
);
|
||||
const clear3 = setClick(buttonRef.current, onClick);
|
||||
const clear4 = setClickCapture(
|
||||
buttonRef.current,
|
||||
onClickCapture,
|
||||
);
|
||||
|
||||
return () => {
|
||||
clear1();
|
||||
clear2();
|
||||
clear3();
|
||||
clear4();
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -2693,13 +2860,13 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const clickEvent = jest.fn();
|
||||
const buttonRef = React.createRef();
|
||||
const TestScope = React.unstable_createScope();
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test() {
|
||||
const scopeRef = React.useRef(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
click.setListener(scopeRef.current, clickEvent);
|
||||
return setClick(scopeRef.current, clickEvent);
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -2726,15 +2893,20 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const innerOnClick = jest.fn(e => e.stopPropagation());
|
||||
const TestScope = React.unstable_createScope();
|
||||
const TestScope2 = React.unstable_createScope();
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test() {
|
||||
const scopeRef = React.useRef(null);
|
||||
const scope2Ref = React.useRef(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
click.setListener(scopeRef.current, outerOnClick);
|
||||
click.setListener(scope2Ref.current, innerOnClick);
|
||||
const clear1 = setClick(scopeRef.current, outerOnClick);
|
||||
const clear2 = setClick(scope2Ref.current, innerOnClick);
|
||||
|
||||
return () => {
|
||||
clear1();
|
||||
clear2();
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -2763,15 +2935,20 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const innerOnClick = jest.fn();
|
||||
const TestScope = React.unstable_createScope();
|
||||
const TestScope2 = React.unstable_createScope();
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test() {
|
||||
const scopeRef = React.useRef(null);
|
||||
const scope2Ref = React.useRef(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
click.setListener(scopeRef.current, outerOnClick);
|
||||
click.setListener(scope2Ref.current, innerOnClick);
|
||||
const clear1 = setClick(scopeRef.current, outerOnClick);
|
||||
const clear2 = setClick(scope2Ref.current, innerOnClick);
|
||||
|
||||
return () => {
|
||||
clear1();
|
||||
clear2();
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -2799,15 +2976,20 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const onClick = jest.fn(e => e.stopPropagation());
|
||||
const TestScope = React.unstable_createScope();
|
||||
const TestScope2 = React.unstable_createScope();
|
||||
const click = ReactDOM.unstable_createEventHandle('click');
|
||||
const setClick = ReactDOM.unstable_createEventHandle('click');
|
||||
|
||||
function Test() {
|
||||
const scopeRef = React.useRef(null);
|
||||
const scope2Ref = React.useRef(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
click.setListener(scopeRef.current, onClick);
|
||||
click.setListener(scope2Ref.current, onClick);
|
||||
const clear1 = setClick(scopeRef.current, onClick);
|
||||
const clear2 = setClick(scope2Ref.current, onClick);
|
||||
|
||||
return () => {
|
||||
clear1();
|
||||
clear2();
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
12
packages/react-dom/src/shared/ReactDOMTypes.js
vendored
12
packages/react-dom/src/shared/ReactDOMTypes.js
vendored
@@ -78,17 +78,13 @@ export type ReactDOMResponderContext = {
|
||||
...
|
||||
};
|
||||
|
||||
export type ReactDOMEventHandle = {|
|
||||
setListener(
|
||||
target: EventTarget | ReactScopeInstance,
|
||||
callback: (SyntheticEvent<EventTarget>) => void,
|
||||
): void,
|
||||
clear(): void,
|
||||
|};
|
||||
export type ReactDOMEventHandle = (
|
||||
target: EventTarget | ReactScopeInstance,
|
||||
callback: (SyntheticEvent<EventTarget>) => void,
|
||||
) => () => void;
|
||||
|
||||
export type ReactDOMEventHandleListener = {|
|
||||
callback: (SyntheticEvent<EventTarget>) => void,
|
||||
capture: boolean,
|
||||
destroy: (target: EventTarget | ReactScopeInstance) => void,
|
||||
type: DOMTopLevelEventType,
|
||||
|};
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
|
||||
const {useEffect, useRef} = React;
|
||||
const {useLayoutEffect, useRef} = React;
|
||||
const {unstable_createEventHandle: createEventHandle} = ReactDOM;
|
||||
|
||||
type UseEventHandle = {|
|
||||
@@ -30,20 +30,48 @@ export default function useEvent(
|
||||
|},
|
||||
): UseEventHandle {
|
||||
const handleRef = useRef(null);
|
||||
let setListener;
|
||||
let clears;
|
||||
let useEventHandle;
|
||||
|
||||
if (handleRef.current == null) {
|
||||
handleRef.current = createEventHandle(event, options);
|
||||
setListener = createEventHandle(event, options);
|
||||
clears = new Map();
|
||||
useEventHandle = {
|
||||
setListener(
|
||||
target: EventTarget,
|
||||
callback: null | ((SyntheticEvent<EventTarget>) => void),
|
||||
): void {
|
||||
let clear = clears.get(target);
|
||||
if (clear !== undefined) {
|
||||
clear();
|
||||
}
|
||||
if (callback === null) {
|
||||
clears.delete(target);
|
||||
return;
|
||||
}
|
||||
clear = setListener(target, callback);
|
||||
clears.set(target, clear);
|
||||
},
|
||||
clear(): void {
|
||||
const clearsArr = Array.from(clears.values());
|
||||
for (let i = 0; i < clearsArr.length; i++) {
|
||||
clearsArr[i]();
|
||||
}
|
||||
clears.clear();
|
||||
},
|
||||
};
|
||||
handleRef.current = {setListener, clears, useEventHandle};
|
||||
} else {
|
||||
({setListener, clears, useEventHandle} = handleRef.current);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const handle = handleRef.current;
|
||||
useLayoutEffect(() => {
|
||||
return () => {
|
||||
if (handle !== null) {
|
||||
handle.clear();
|
||||
}
|
||||
useEventHandle.clear();
|
||||
handleRef.current = null;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return ((handleRef.current: any): UseEventHandle);
|
||||
return useEventHandle;
|
||||
}
|
||||
|
||||
@@ -479,10 +479,6 @@ export function getInstanceFromNode(node: any) {
|
||||
throw new Error('Not yet implemented.');
|
||||
}
|
||||
|
||||
export function removeInstanceEventHandles(instance: any) {
|
||||
// noop
|
||||
}
|
||||
|
||||
export function isOpaqueHydratingObject(value: mixed): boolean {
|
||||
throw new Error('Not yet implemented');
|
||||
}
|
||||
|
||||
@@ -532,10 +532,6 @@ export function getInstanceFromNode(node: any) {
|
||||
throw new Error('Not yet implemented.');
|
||||
}
|
||||
|
||||
export function removeInstanceEventHandles(instance: any) {
|
||||
// noop
|
||||
}
|
||||
|
||||
export function isOpaqueHydratingObject(value: mixed): boolean {
|
||||
throw new Error('Not yet implemented');
|
||||
}
|
||||
|
||||
@@ -438,10 +438,6 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
|
||||
throw new Error('Not yet implemented.');
|
||||
},
|
||||
|
||||
removeInstanceEventHandles(instance: any): void {
|
||||
// NO-OP
|
||||
},
|
||||
|
||||
beforeActiveInstanceBlur() {
|
||||
// NO-OP
|
||||
},
|
||||
@@ -456,8 +452,6 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
|
||||
|
||||
prepareScopeUpdate() {},
|
||||
|
||||
removeScopeEventHandles() {},
|
||||
|
||||
getInstanceFromScope() {
|
||||
throw new Error('Not yet implemented.');
|
||||
},
|
||||
|
||||
@@ -35,7 +35,6 @@ import {
|
||||
enableFundamentalAPI,
|
||||
enableSuspenseCallback,
|
||||
enableScopeAPI,
|
||||
enableCreateEventHandleAPI,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import {
|
||||
FunctionComponent,
|
||||
@@ -109,10 +108,8 @@ import {
|
||||
updateFundamentalComponent,
|
||||
commitHydratedContainer,
|
||||
commitHydratedSuspenseInstance,
|
||||
removeInstanceEventHandles,
|
||||
clearContainer,
|
||||
prepareScopeUpdate,
|
||||
removeScopeEventHandles,
|
||||
} from './ReactFiberHostConfig';
|
||||
import {
|
||||
captureCommitPhaseError,
|
||||
@@ -928,9 +925,6 @@ function commitUnmount(
|
||||
if (enableDeprecatedFlareAPI) {
|
||||
unmountDeprecatedResponderListeners(current);
|
||||
}
|
||||
if (enableCreateEventHandleAPI && current.ref !== null) {
|
||||
removeInstanceEventHandles(current.stateNode);
|
||||
}
|
||||
safelyDetachRef(current);
|
||||
return;
|
||||
}
|
||||
@@ -972,10 +966,6 @@ function commitUnmount(
|
||||
if (enableDeprecatedFlareAPI) {
|
||||
unmountDeprecatedResponderListeners(current);
|
||||
}
|
||||
const scopeInstance = current.stateNode;
|
||||
if (enableCreateEventHandleAPI && current.ref !== null) {
|
||||
removeScopeEventHandles(scopeInstance);
|
||||
}
|
||||
safelyDetachRef(current);
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -35,7 +35,6 @@ import {
|
||||
enableFundamentalAPI,
|
||||
enableSuspenseCallback,
|
||||
enableScopeAPI,
|
||||
enableCreateEventHandleAPI,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import {
|
||||
FunctionComponent,
|
||||
@@ -109,10 +108,8 @@ import {
|
||||
updateFundamentalComponent,
|
||||
commitHydratedContainer,
|
||||
commitHydratedSuspenseInstance,
|
||||
removeInstanceEventHandles,
|
||||
clearContainer,
|
||||
prepareScopeUpdate,
|
||||
removeScopeEventHandles,
|
||||
} from './ReactFiberHostConfig';
|
||||
import {
|
||||
captureCommitPhaseError,
|
||||
@@ -928,9 +925,6 @@ function commitUnmount(
|
||||
if (enableDeprecatedFlareAPI) {
|
||||
unmountDeprecatedResponderListeners(current);
|
||||
}
|
||||
if (enableCreateEventHandleAPI && current.ref !== null) {
|
||||
removeInstanceEventHandles(current.stateNode);
|
||||
}
|
||||
safelyDetachRef(current);
|
||||
return;
|
||||
}
|
||||
@@ -972,10 +966,6 @@ function commitUnmount(
|
||||
if (enableDeprecatedFlareAPI) {
|
||||
unmountDeprecatedResponderListeners(current);
|
||||
}
|
||||
const scopeInstance = current.stateNode;
|
||||
if (enableCreateEventHandleAPI && current.ref !== null) {
|
||||
removeScopeEventHandles(scopeInstance);
|
||||
}
|
||||
safelyDetachRef(current);
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -23,5 +23,4 @@ function shim(...args: any) {
|
||||
|
||||
// React Scopes (when unsupported)
|
||||
export const prepareScopeUpdate = shim;
|
||||
export const removeScopeEventHandles = shim;
|
||||
export const getInstanceFromScope = shim;
|
||||
|
||||
@@ -72,8 +72,6 @@ export const mountFundamentalComponent =
|
||||
export const shouldUpdateFundamentalComponent =
|
||||
$$$hostConfig.shouldUpdateFundamentalComponent;
|
||||
export const getInstanceFromNode = $$$hostConfig.getInstanceFromNode;
|
||||
export const removeInstanceEventHandles =
|
||||
$$$hostConfig.removeInstanceEventHandles;
|
||||
export const isOpaqueHydratingObject = $$$hostConfig.isOpaqueHydratingObject;
|
||||
export const makeOpaqueHydratingObject =
|
||||
$$$hostConfig.makeOpaqueHydratingObject;
|
||||
@@ -83,7 +81,6 @@ export const beforeActiveInstanceBlur = $$$hostConfig.beforeActiveInstanceBlur;
|
||||
export const afterActiveInstanceBlur = $$$hostConfig.afterActiveInstanceBlur;
|
||||
export const preparePortalMount = $$$hostConfig.preparePortalMount;
|
||||
export const prepareScopeUpdate = $$$hostConfig.preparePortalMount;
|
||||
export const removeScopeEventHandles = $$$hostConfig.removeScopeEventHandles;
|
||||
export const getInstanceFromScope = $$$hostConfig.getInstanceFromScope;
|
||||
|
||||
// -------------------
|
||||
|
||||
@@ -383,10 +383,6 @@ export function getInstanceFromNode(mockNode: Object) {
|
||||
return null;
|
||||
}
|
||||
|
||||
export function removeInstanceEventHandles(instance: any) {
|
||||
// noop
|
||||
}
|
||||
|
||||
let clientId: number = 0;
|
||||
export function makeClientId(): OpaqueIDType {
|
||||
return 'c_' + (clientId++).toString(36);
|
||||
@@ -440,10 +436,6 @@ export function prepareScopeUpdate(scopeInstance: Object, inst: Object): void {
|
||||
nodeToInstanceMap.set(scopeInstance, inst);
|
||||
}
|
||||
|
||||
export function removeScopeEventHandles(scopeInstance: Object): void {
|
||||
nodeToInstanceMap.delete(scopeInstance);
|
||||
}
|
||||
|
||||
export function getInstanceFromScope(scopeInstance: Object): null | Object {
|
||||
return nodeToInstanceMap.get(scopeInstance) || null;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
{
|
||||
"0": "React.addons.createFragment(...): Encountered an invalid child; DOM elements are not valid children of React components.",
|
||||
"1": "update(): expected target of %s to be an array; got %s.",
|
||||
@@ -366,5 +365,7 @@
|
||||
"365": "Invalid selector type %s specified.",
|
||||
"366": "ReactDOM.createEventHandle: setListener called on an target that did not have a corresponding root. This is likely a bug in React.",
|
||||
"367": "ReactDOM.createEventHandle: setListener called on an element target that is not managed by React. Ensure React rendered the DOM element.",
|
||||
"368": "ReactDOM.createEventHandle: setListener called on an invalid target. Provide a valid EventTarget or an element managed by React."
|
||||
"368": "ReactDOM.createEventHandle: setListener called on an invalid target. Provide a valid EventTarget or an element managed by React.",
|
||||
"369": "ReactDOM.createEventHandle: setter called on an invalid target. Provide a valid EventTarget or an element managed by React.",
|
||||
"370": "ReactDOM.createEventHandle: setter called with an invalid callback. The callback must be a function."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user