Skip to content

Commit 7a482af

Browse files
authored
Event API: Fix bug where Press root events were not being cleared (#15507)
1 parent a14e24e commit 7a482af

File tree

2 files changed

+41
-5
lines changed

2 files changed

+41
-5
lines changed

packages/react-events/src/Press.js

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ type PressProps = {
4444
type PointerType = '' | 'mouse' | 'keyboard' | 'pen' | 'touch';
4545

4646
type PressState = {
47+
addedRootEvents: boolean,
4748
isActivePressed: boolean,
4849
isActivePressStart: boolean,
4950
isLongPressed: boolean,
@@ -300,6 +301,7 @@ function dispatchPressEndEvents(
300301
deactivate(context, props, state);
301302
}
302303
}
304+
removeRootEventTypes(context, state);
303305
}
304306

305307
function isAnchorTagElement(eventTarget: EventTarget): boolean {
@@ -394,7 +396,6 @@ function unmountResponder(
394396
): void {
395397
if (state.isPressed) {
396398
dispatchPressEndEvents(context, props, state);
397-
context.removeRootEventTypes(rootEventTypes);
398399
}
399400
}
400401

@@ -411,15 +412,35 @@ function dispatchCancel(
411412
} else {
412413
state.ignoreEmulatedMouseEvents = false;
413414
dispatchPressEndEvents(context, props, state);
414-
context.removeRootEventTypes(rootEventTypes);
415415
}
416416
}
417417
}
418418

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+
419439
const PressResponder = {
420440
targetEventTypes,
421441
createInitialState(): PressState {
422442
return {
443+
addedRootEvents: false,
423444
didDispatchEvent: false,
424445
isActivePressed: false,
425446
isActivePressStart: false,
@@ -447,7 +468,6 @@ const PressResponder = {
447468

448469
if (props.disabled) {
449470
dispatchPressEndEvents(context, props, state);
450-
context.removeRootEventTypes(rootEventTypes);
451471
state.ignoreEmulatedMouseEvents = false;
452472
return;
453473
}
@@ -500,7 +520,7 @@ const PressResponder = {
500520
);
501521
state.isPressWithinResponderRegion = true;
502522
dispatchPressStartEvents(context, props, state);
503-
context.addRootEventTypes(rootEventTypes);
523+
addRootEventTypes(context, state);
504524
} else {
505525
// Prevent spacebar press from scrolling the window
506526
if (isValidKeyPress(nativeEvent.key) && nativeEvent.key === ' ') {
@@ -630,7 +650,6 @@ const PressResponder = {
630650
}
631651
}
632652
}
633-
context.removeRootEventTypes(rootEventTypes);
634653
} else if (type === 'mouseup' && state.ignoreEmulatedMouseEvents) {
635654
state.ignoreEmulatedMouseEvents = false;
636655
}

packages/react-events/src/__tests__/Press-test.internal.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,4 +1428,21 @@ describe('Event responder: Press', () => {
14281428
it('expect displayName to show up for event component', () => {
14291429
expect(Press.displayName).toBe('Press');
14301430
});
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+
});
14311448
});

0 commit comments

Comments
 (0)