@samitouri / QOS-React / commits / 7a482af5d8

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 });