diff --git a/src/ghQueueMicrotask.ts b/src/ghQueueMicrotask.ts new file mode 100644 index 0000000000..b0570292c3 --- /dev/null +++ b/src/ghQueueMicrotask.ts @@ -0,0 +1,5 @@ +// `queueMicrotask` was introduced to react-native in version 0.66 (https://github.com/react-native-community/releases/blob/master/CHANGELOG.md#v0660) +// Because Gesture Handler supports versions 0.64+, we have to handle situations where someone uses older version of react native. +// That's why if `queueMicrotask` doesn't exist, we use `setImmediate` instead, since it was used before we switched to `queueMicrotask` in version 2.11.0 +export const ghQueueMicrotask = + typeof queueMicrotask === 'function' ? queueMicrotask : setImmediate; diff --git a/src/handlers/createHandler.tsx b/src/handlers/createHandler.tsx index 15fb32054e..7f991fed1c 100644 --- a/src/handlers/createHandler.tsx +++ b/src/handlers/createHandler.tsx @@ -29,6 +29,7 @@ import { isFabric, isJestEnv, tagMessage } from '../utils'; import { ActionType } from '../ActionType'; import { PressabilityDebugView } from './PressabilityDebugView'; import GestureHandlerRootViewContext from '../GestureHandlerRootViewContext'; +import { ghQueueMicrotask } from '../ghQueueMicrotask'; const UIManagerAny = UIManager as any; @@ -214,7 +215,7 @@ export default function createHandler< // queueMicrotask. This makes it so update() function gets called after all // react components are mounted and we expect the missing ref object to // be resolved by then. - queueMicrotask(() => { + ghQueueMicrotask(() => { this.update(UNRESOLVED_REFS_RETRY_LIMIT); }); } @@ -378,7 +379,7 @@ export default function createHandler< // `ref={refObject}` it's possible that it won't be resolved in time. Seems like trying // again is easy enough fix. if (hasUnresolvedRefs(props) && remainingTries > 0) { - queueMicrotask(() => { + ghQueueMicrotask(() => { this.update(remainingTries - 1); }); } else { diff --git a/src/handlers/gestureHandlerCommon.ts b/src/handlers/gestureHandlerCommon.ts index 7f28fd0c2a..9e795e1439 100644 --- a/src/handlers/gestureHandlerCommon.ts +++ b/src/handlers/gestureHandlerCommon.ts @@ -11,6 +11,7 @@ import { ValueOf } from '../typeUtils'; import { handlerIDToTag } from './handlersRegistry'; import { toArray } from '../utils'; import RNGestureHandlerModule from '../RNGestureHandlerModule'; +import { ghQueueMicrotask } from '../ghQueueMicrotask'; const commonProps = [ 'id', @@ -235,7 +236,7 @@ let flushOperationsScheduled = false; export function scheduleFlushOperations() { if (!flushOperationsScheduled) { flushOperationsScheduled = true; - queueMicrotask(() => { + ghQueueMicrotask(() => { RNGestureHandlerModule.flushOperations(); flushOperationsScheduled = false; diff --git a/src/handlers/gestures/GestureDetector.tsx b/src/handlers/gestures/GestureDetector.tsx index 27e141538b..588984bc60 100644 --- a/src/handlers/gestures/GestureDetector.tsx +++ b/src/handlers/gestures/GestureDetector.tsx @@ -51,6 +51,7 @@ import { RNRenderer } from '../../RNRenderer'; import { isNewWebImplementationEnabled } from '../../EnableNewWebImplementation'; import { nativeViewGestureHandlerProps } from '../NativeViewGestureHandler'; import GestureHandlerRootViewContext from '../../GestureHandlerRootViewContext'; +import { ghQueueMicrotask } from '../../ghQueueMicrotask'; declare const global: { isFormsStackingContext: (node: unknown) => boolean | null; // JSI function @@ -159,7 +160,7 @@ function attachHandlers({ // use queueMicrotask to extract handlerTags, because all refs should be initialized // when it's ran - queueMicrotask(() => { + ghQueueMicrotask(() => { if (!mountedRef.current) { return; } @@ -179,7 +180,7 @@ function attachHandlers({ // use queueMicrotask to extract handlerTags, because all refs should be initialized // when it's ran - queueMicrotask(() => { + ghQueueMicrotask(() => { if (!mountedRef.current) { return; } @@ -267,7 +268,7 @@ function updateHandlers( // use queueMicrotask to extract handlerTags, because when it's ran, all refs should be updated // and handlerTags in BaseGesture references should be updated in the loop above (we need to wait // in case of external relations) - queueMicrotask(() => { + ghQueueMicrotask(() => { if (!mountedRef.current) { return; } diff --git a/src/web_hammer/GestureHandler.ts b/src/web_hammer/GestureHandler.ts index 1fcc27e5e6..4ff297fffd 100644 --- a/src/web_hammer/GestureHandler.ts +++ b/src/web_hammer/GestureHandler.ts @@ -6,6 +6,7 @@ import { findNodeHandle } from 'react-native'; import { State } from '../State'; import { EventMap } from './constants'; import * as NodeManager from './NodeManager'; +import { ghQueueMicrotask } from '../ghQueueMicrotask'; // TODO(TS) Replace with HammerInput if https://github.com/DefinitelyTyped/DefinitelyTyped/pull/50438/files is merged export type HammerInputExt = Omit; @@ -508,7 +509,7 @@ abstract class GestureHandler { .filter((v) => v); if (shouldUseTouchEvents !== this.shouldUseTouchEvents(props)) { - queueMicrotask(() => { + ghQueueMicrotask(() => { // if the undelying event API needs to be changed, we need to unmount and mount // the hammer instance again. this.destroy();