Event API: Fix bug where Press root events were not being cleared (#15507)
Dominic Gannaway committed
Apr 26, 2019 at 10:30 UTC
7a482af5d89cfb76bce29a2db00a174a5f1766c9
2 files changed
+41
-5
packages/react-events/src/Press.js
+24
-5
@@ -44,6 +44,7 @@ type PressProps = {
44
type PointerType = '' | 'mouse' | 'keyboard' | 'pen' | 'touch';
45
46
type PressState = {
47
+ addedRootEvents: boolean,
48
isActivePressed: boolean,
49
isActivePressStart: boolean,
50
isLongPressed: boolean,
@@ -300,6 +301,7 @@ function dispatchPressEndEvents(
301
deactivate(context, props, state);
302
}
303
}
304
+ removeRootEventTypes(context, state);
305
}
306
307
function isAnchorTagElement(eventTarget: EventTarget): boolean {
@@ -394,7 +396,6 @@ function unmountResponder(
396
): void {
397
if (state.isPressed) {
398
dispatchPressEndEvents(context, props, state);
397
- context.removeRootEventTypes(rootEventTypes);
399
}
400
}
401
@@ -411,15 +412,35 @@ function dispatchCancel(
412
} else {
413
state.ignoreEmulatedMouseEvents = false;
414
dispatchPressEndEvents(context, props, state);
414
- context.removeRootEventTypes(rootEventTypes);
415
}
416
}
417
}
418
419
+function addRootEventTypes(
420
+ context: ReactResponderContext,
421
+ state: PressState,
422
+): void {
423
+ if (!state.addedRootEvents) {
424
+ state.addedRootEvents = true;
425
+ context.addRootEventTypes(rootEventTypes);
426
+ }
427
+}
428
+
429
+function removeRootEventTypes(
430
+ context: ReactResponderContext,
431
+ state: PressState,
432
+): void {
433
+ if (state.addedRootEvents) {
434
+ state.addedRootEvents = false;
435
+ context.removeRootEventTypes(rootEventTypes);
436
+ }
437
+}
438
+
439
const PressResponder = {
440
targetEventTypes,
441
createInitialState(): PressState {
442
return {
443
+ addedRootEvents: false,
444
didDispatchEvent: false,
445
isActivePressed: false,
446
isActivePressStart: false,
@@ -447,7 +468,6 @@ const PressResponder = {
468
469
if (props.disabled) {
470
dispatchPressEndEvents(context, props, state);
450
- context.removeRootEventTypes(rootEventTypes);
471
state.ignoreEmulatedMouseEvents = false;
472
return;
473
}
@@ -500,7 +520,7 @@ const PressResponder = {
520
);
521
state.isPressWithinResponderRegion = true;
522
dispatchPressStartEvents(context, props, state);
503
- context.addRootEventTypes(rootEventTypes);
523
+ addRootEventTypes(context, state);
524
} else {
525
// Prevent spacebar press from scrolling the window
526
if (isValidKeyPress(nativeEvent.key) && nativeEvent.key === ' ') {
@@ -630,7 +650,6 @@ const PressResponder = {
650
}
651
}
652
}
633
- context.removeRootEventTypes(rootEventTypes);
653
} else if (type === 'mouseup' && state.ignoreEmulatedMouseEvents) {
654
state.ignoreEmulatedMouseEvents = false;
655
}
packages/react-events/src/__tests__/Press-test.internal.js
+17
@@ -1428,4 +1428,21 @@ describe('Event responder: Press', () => {
1428
it('expect displayName to show up for event component', () => {
1429
expect(Press.displayName).toBe('Press');
1430
});
1431
+
1432
+ it('should not trigger an invariant in addRootEventTypes()', () => {
1433
+ const ref = React.createRef();
1434
+ const element = (
1435
+ <Press>
1436
+ <button ref={ref} />
1437
+ </Press>
1438
+ );
1439
+ ReactDOM.render(element, container);
1440
+
1441
+ ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1442
+ jest.advanceTimersByTime(DEFAULT_LONG_PRESS_DELAY);
1443
+ ref.current.dispatchEvent(createPointerEvent('pointermove'));
1444
+ ref.current.dispatchEvent(createPointerEvent('pointerup'));
1445
+ ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1446
+ ReactDOM.render(element, container);
1447
+ });
1448
});