From 972317c17cfb223f5177c888e90ef32c86fe846a Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Wed, 27 May 2020 13:54:03 -0700 Subject: [PATCH] PressResponder fix invariant edge case If keyup events fall through to a "pressable" element that is not the responder (e.g., a keydown in a modal closes the modal) it should not attempt to transition the state. Also replace invariant with console.error to allow the app to recover if unexpected signals occur. --- .../hooks/usePressEvents/PressResponder.js | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/packages/react-native-web/src/hooks/usePressEvents/PressResponder.js b/packages/react-native-web/src/hooks/usePressEvents/PressResponder.js index 66059ede..dd622f35 100644 --- a/packages/react-native-web/src/hooks/usePressEvents/PressResponder.js +++ b/packages/react-native-web/src/hooks/usePressEvents/PressResponder.js @@ -10,8 +10,6 @@ 'use strict'; -import invariant from 'fbjs/lib/invariant'; - type ClickEvent = any; type KeyboardEvent = any; type ResponderEvent = any; @@ -222,7 +220,7 @@ export default class PressResponder { _longPressDispatched: ?boolean = false; _pressDelayTimeout: ?TimeoutID = null; _pressOutDelayTimeout: ?TimeoutID = null; - _responderID: ?any; + _responder: ?any; _selectionTerminated: ?boolean; _touchActivatePosition: ?$ReadOnly<{| pageX: number, @@ -264,7 +262,7 @@ export default class PressResponder { this._cancelPressOutDelayTimeout(); this._longPressDispatched = false; - this._responderID = event.currentTarget; + this._responder = event.currentTarget; this._selectionTerminated = false; this._touchState = NOT_RESPONDER; this._isPointerTouch = event.nativeEvent.type === 'touchstart'; @@ -319,7 +317,9 @@ export default class PressResponder { onKeyUp: event => { if (isValidKeyPress(event)) { - end(event); + if (this._touchState !== NOT_RESPONDER) { + end(event); + } event.stopPropagation(); } }, @@ -411,17 +411,12 @@ export default class PressResponder { if (Transitions[prevState] != null) { nextState = Transitions[prevState][signal]; } - if (this._responderID == null && signal === RESPONDER_RELEASE) { + if (this._responder == null && signal === RESPONDER_RELEASE) { return; } - invariant( - nextState != null && nextState !== ERROR, - 'PressResponder: Invalid signal `%s` for state `%s` on responder: %s', - signal, - prevState, - this._responderID - ); - if (prevState !== nextState) { + if (nextState == null || nextState === ERROR) { + console.error(`PressResponder: Invalid signal ${signal} for state ${prevState} on responder`); + } else if (prevState !== nextState) { this._performTransitionSideEffects(prevState, nextState, signal, event); this._touchState = nextState; }