Skip to content

Commit a90015f

Browse files
committed
Address feedback
Address feedback Address feedback Address feedback #2 Adjust changes
1 parent c208ac1 commit a90015f

7 files changed

Lines changed: 87 additions & 76 deletions

File tree

packages/legacy-events/PluginModuleType.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export type PluginModule<NativeEvent> = {
2929
nativeTarget: NativeEvent,
3030
nativeEventTarget: null | EventTarget,
3131
eventSystemFlags: EventSystemFlags,
32-
container?: EventTarget,
32+
container?: null | EventTarget,
3333
) => ?ReactSyntheticEvent,
3434
tapMoveThreshold?: number,
3535
};

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

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ import {
6969
enableUseEventAPI,
7070
} from 'shared/ReactFeatureFlags';
7171
import {HostComponent} from 'shared/ReactWorkTags';
72-
import invariant from 'shared/invariant';
7372
import {
7473
RESPONDER_EVENT_SYSTEM,
7574
IS_PASSIVE,
@@ -1093,35 +1092,19 @@ export function mountEventListener(listener: ReactDOMListener): void {
10931092
// TODO (useEvent)
10941093
} else if (isDOMElement(target)) {
10951094
attachElementListener(listener);
1096-
} else {
1097-
// The user should never get to here or we missed something in
1098-
// validateEventListenerTarget below.
1099-
invariant(
1100-
false,
1101-
'A useEvent listener target instance was not handled. This error is ' +
1102-
'likely caused by a bug in React. Please file an issue.',
1103-
);
11041095
}
11051096
}
11061097
}
11071098

11081099
export function unmountEventListener(listener: ReactDOMListener): void {
11091100
if (enableUseEventAPI) {
11101101
const {target} = listener;
1111-
if (isDOMElement(target)) {
1102+
if (target === window) {
11121103
// TODO (useEvent)
11131104
} else if (isDOMDocument(target)) {
11141105
// TODO (useEvent)
11151106
} else if (isDOMElement(target)) {
11161107
detachElementListener(listener);
1117-
} else {
1118-
// The user should never get to here or we missed something in
1119-
// validateEventListenerTarget below.
1120-
invariant(
1121-
false,
1122-
'A useEvent listener target instance was not handled. This error is ' +
1123-
'likely caused by a bug in React. Please file an issue.',
1124-
);
11251108
}
11261109
}
11271110
}
@@ -1150,9 +1133,11 @@ export function validateEventListenerTarget(
11501133
}
11511134
if (__DEV__) {
11521135
console.warn(
1153-
'Event listener method setListener() from useEvent() hook requires the first argument to be either a valid ' +
1154-
'DOM node that was rendered and managed by React, or either the "window" or "document" objects.' +
1155-
"If you are setting setListener from ref, ensure the ref's current value has been set and is not null.",
1136+
'Event listener method setListener() from useEvent() hook requires the first argument to be either:' +
1137+
'\n\n' +
1138+
'1. A valid DOM node that was rendered and managed by React' +
1139+
'2. The "window" object' +
1140+
'3. The "document" object',
11561141
);
11571142
}
11581143
}

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

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ function dispatchEventsForPlugins(
115115
eventSystemFlags: EventSystemFlags,
116116
nativeEvent: AnyNativeEvent,
117117
targetInst: null | Fiber,
118-
rootContainer: EventTarget,
118+
targetContainer: null | EventTarget,
119119
): void {
120120
const nativeEventTarget = getEventTarget(nativeEvent);
121121
const syntheticEvents: Array<ReactSyntheticEvent> = [];
@@ -129,7 +129,7 @@ function dispatchEventsForPlugins(
129129
nativeEvent,
130130
nativeEventTarget,
131131
eventSystemFlags,
132-
rootContainer,
132+
targetContainer,
133133
);
134134
if (isArray(extractedEvents)) {
135135
// Flow complains about @@iterator being missing in ReactSyntheticEvent,
@@ -209,7 +209,7 @@ function willDeferLaterForFBLegacyPrimer(nativeEvent: any): boolean {
209209
const legacyFBSupport = true;
210210
const isCapture = nativeEvent.eventPhase === 1;
211211
addTrappedEventListener(
212-
document,
212+
null,
213213
((type: any): DOMTopLevelEventType),
214214
isCapture,
215215
legacyFBSupport,
@@ -223,18 +223,18 @@ function willDeferLaterForFBLegacyPrimer(nativeEvent: any): boolean {
223223

224224
function isMatchingRootContainer(
225225
grandContainer: Element,
226-
rootContainer: EventTarget,
226+
targetContainer: EventTarget,
227227
): boolean {
228228
return (
229-
grandContainer === rootContainer ||
229+
grandContainer === targetContainer ||
230230
(grandContainer.nodeType === COMMENT_NODE &&
231-
grandContainer.parentNode === rootContainer)
231+
grandContainer.parentNode === targetContainer)
232232
);
233233
}
234234

235235
export function isDOMElement(target: EventTarget): boolean {
236236
const nodeType = ((target: any): Node).nodeType;
237-
return nodeType != null && nodeType === ELEMENT_NODE;
237+
return (nodeType: any) && nodeType === ELEMENT_NODE;
238238
}
239239

240240
export function isDOMDocument(target: EventTarget): boolean {
@@ -247,14 +247,22 @@ export function dispatchEventForPluginEventSystem(
247247
eventSystemFlags: EventSystemFlags,
248248
nativeEvent: AnyNativeEvent,
249249
targetInst: null | Fiber,
250-
rootContainer: EventTarget,
250+
targetContainer: null | EventTarget,
251251
): void {
252252
let ancestorInst = targetInst;
253-
// Given the rootContainer can be any EventTarget, if the
254-
// target is not a valid DOM element then we'll skip this part.
255-
if (isDOMElement(rootContainer)) {
253+
if (targetContainer !== null) {
254+
const possibleTargetContainerNode = ((targetContainer: any): Node);
255+
// Given the rootContainer can be any EventTarget, if the
256+
// target is not a valid DOM element then we'll skip this part.
257+
if (
258+
possibleTargetContainerNode === window ||
259+
!isDOMElement(possibleTargetContainerNode)
260+
) {
261+
// TODO: useEvent for document and window
262+
return;
263+
}
256264
// If we detect the FB legacy primer system, we
257-
// defer the event to the "document" with a one
265+
// defer the event to the null with a one
258266
// time event listener so we can defer the event.
259267
if (
260268
enableLegacyFBPrimerSupport &&
@@ -281,7 +289,7 @@ export function dispatchEventForPluginEventSystem(
281289
}
282290
if (node.tag === HostRoot || node.tag === HostPortal) {
283291
const container = node.stateNode.containerInfo;
284-
if (isMatchingRootContainer(container, rootContainer)) {
292+
if (isMatchingRootContainer(container, possibleTargetContainerNode)) {
285293
break;
286294
}
287295
if (node.tag === HostPortal) {
@@ -293,7 +301,12 @@ export function dispatchEventForPluginEventSystem(
293301
while (grandNode !== null) {
294302
if (grandNode.tag === HostRoot || grandNode.tag === HostPortal) {
295303
const grandContainer = grandNode.stateNode.containerInfo;
296-
if (isMatchingRootContainer(grandContainer, rootContainer)) {
304+
if (
305+
isMatchingRootContainer(
306+
grandContainer,
307+
possibleTargetContainerNode,
308+
)
309+
) {
297310
// This is the rootContainer we're looking for and we found it as
298311
// a parent of the Portal. That means we can ignore it because the
299312
// Portal will bubble through to us.
@@ -320,7 +333,7 @@ export function dispatchEventForPluginEventSystem(
320333
eventSystemFlags,
321334
nativeEvent,
322335
ancestorInst,
323-
rootContainer,
336+
targetContainer,
324337
),
325338
);
326339
}
@@ -347,11 +360,13 @@ export function attachElementListener(listener: ReactDOMListener): void {
347360
// find the nearest root/portal contained to attach the event listener
348361
// to. If it's not managed, i.e. the window, then we just attach
349362
// the listener to the target.
350-
const possibleManagedTarget = ((target: any): Element);
351-
if (getClosestInstanceFromNode(possibleManagedTarget)) {
352-
containerEventTarget = getNearestRootOrPortalContainer(
353-
possibleManagedTarget,
354-
);
363+
if (isDOMElement(target)) {
364+
const possibleManagedTarget = ((target: any): Element);
365+
if (getClosestInstanceFromNode(possibleManagedTarget)) {
366+
containerEventTarget = getNearestRootOrPortalContainer(
367+
possibleManagedTarget,
368+
);
369+
}
355370
}
356371
const listenerMap = getListenerMapForElement(containerEventTarget);
357372
// Add the event listener to the target container (falling back to

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

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ export function addResponderEventSystemEvent(
132132
}
133133

134134
export function addTrappedEventListener(
135-
targetContainer: EventTarget,
135+
targetContainer: null | EventTarget,
136136
topLevelType: DOMTopLevelEventType,
137137
capture: boolean,
138138
legacyFBSupport?: boolean,
@@ -165,6 +165,18 @@ export function addTrappedEventListener(
165165
targetContainer,
166166
);
167167

168+
// When the targetContainer is null, it means that the container
169+
// target is null, but really we need a real DOM node to attach to.
170+
// In this case, we fallback to the "document" node, but leave the
171+
// targetContainer (which is bound in the above function) to null.
172+
// Really, this only happens for TestUtils.Simulate, so when we
173+
// remove that support, we can remove this block of code.
174+
if (targetContainer === null) {
175+
targetContainer = document;
176+
}
177+
178+
const validTargetContainer = ((targetContainer: any): EventTarget);
179+
168180
const rawEventName = getRawEventName(topLevelType);
169181
let fbListener;
170182

@@ -188,7 +200,7 @@ export function addTrappedEventListener(
188200
if (fbListener) {
189201
fbListener.remove();
190202
} else {
191-
targetContainer.removeEventListener(
203+
validTargetContainer.removeEventListener(
192204
((rawEventName: any): string),
193205
(listener: any),
194206
);
@@ -200,14 +212,14 @@ export function addTrappedEventListener(
200212
if (enableUseEventAPI && passive !== undefined) {
201213
// This is only used with passive is either true or false.
202214
fbListener = addEventCaptureListenerWithPassiveFlag(
203-
targetContainer,
215+
validTargetContainer,
204216
rawEventName,
205217
listener,
206218
passive,
207219
);
208220
} else {
209221
fbListener = addEventCaptureListener(
210-
targetContainer,
222+
validTargetContainer,
211223
rawEventName,
212224
listener,
213225
);
@@ -216,14 +228,14 @@ export function addTrappedEventListener(
216228
if (enableUseEventAPI && passive !== undefined) {
217229
// This is only used with passive is either true or false.
218230
fbListener = addEventBubbleListenerWithPassiveFlag(
219-
targetContainer,
231+
validTargetContainer,
220232
rawEventName,
221233
listener,
222234
passive,
223235
);
224236
} else {
225237
fbListener = addEventBubbleListener(
226-
targetContainer,
238+
validTargetContainer,
227239
rawEventName,
228240
listener,
229241
);
@@ -291,7 +303,7 @@ function dispatchUserBlockingUpdate(
291303
export function dispatchEvent(
292304
topLevelType: DOMTopLevelEventType,
293305
eventSystemFlags: EventSystemFlags,
294-
container: EventTarget,
306+
targetContainer: null | EventTarget,
295307
nativeEvent: AnyNativeEvent,
296308
): void {
297309
if (!_enabled) {
@@ -305,7 +317,7 @@ export function dispatchEvent(
305317
null, // Flags that we're not actually blocked on anything as far as we know.
306318
topLevelType,
307319
eventSystemFlags,
308-
container,
320+
targetContainer,
309321
nativeEvent,
310322
);
311323
return;
@@ -314,7 +326,7 @@ export function dispatchEvent(
314326
const blockedOn = attemptToDispatchEvent(
315327
topLevelType,
316328
eventSystemFlags,
317-
container,
329+
targetContainer,
318330
nativeEvent,
319331
);
320332

@@ -330,7 +342,7 @@ export function dispatchEvent(
330342
blockedOn,
331343
topLevelType,
332344
eventSystemFlags,
333-
container,
345+
targetContainer,
334346
nativeEvent,
335347
);
336348
return;
@@ -341,7 +353,7 @@ export function dispatchEvent(
341353
blockedOn,
342354
topLevelType,
343355
eventSystemFlags,
344-
container,
356+
targetContainer,
345357
nativeEvent,
346358
)
347359
) {
@@ -362,7 +374,7 @@ export function dispatchEvent(
362374
eventSystemFlags,
363375
nativeEvent,
364376
null,
365-
container,
377+
targetContainer,
366378
);
367379
} else {
368380
dispatchEventForLegacyPluginEventSystem(
@@ -390,7 +402,7 @@ export function dispatchEvent(
390402
eventSystemFlags,
391403
nativeEvent,
392404
null,
393-
container,
405+
targetContainer,
394406
);
395407
} else {
396408
dispatchEventForLegacyPluginEventSystem(
@@ -407,7 +419,7 @@ export function dispatchEvent(
407419
export function attemptToDispatchEvent(
408420
topLevelType: DOMTopLevelEventType,
409421
eventSystemFlags: EventSystemFlags,
410-
container: EventTarget,
422+
targetContainer: EventTarget | null,
411423
nativeEvent: AnyNativeEvent,
412424
): null | Container | SuspenseInstance {
413425
// TODO: Warn if _enabled is false.
@@ -461,7 +473,7 @@ export function attemptToDispatchEvent(
461473
eventSystemFlags,
462474
nativeEvent,
463475
targetInst,
464-
container,
476+
targetContainer,
465477
);
466478
} else {
467479
dispatchEventForLegacyPluginEventSystem(
@@ -489,7 +501,7 @@ export function attemptToDispatchEvent(
489501
eventSystemFlags,
490502
nativeEvent,
491503
targetInst,
492-
container,
504+
targetContainer,
493505
);
494506
} else {
495507
dispatchEventForLegacyPluginEventSystem(

0 commit comments

Comments
 (0)