Skip to content

Commit ae25b49

Browse files
hannojgm-bert
andauthored
fix: gesture not activating due to outdated handler tag (#3578)
## Description <!-- Description and motivation for this PR. Include 'Fixes #<number>' if this is fixing some issue. --> This fixes an issue where the manual activation of a handler wouldn't work. I unfortunately didn't had time to make a full reproduction. The scenario roughly looks like this: ```ts const gesture = useMemo(() -> Gesture.Pan() // Note happens also without useMemo .manualActivation(true) .onTouchesMove((event, manager) => { // Some criteria to met: manager.activate() }) .onUpdate(() => { // Wouldn't get called on a remount }) return <GestureDetector gesture={gesture}> // ... ``` This is being used in a component on a screen. When we navigate from the screen the component gets unmounted and I can see that his logic is being triggered: https://github.com/software-mansion/react-native-gesture-handler/blob/1e1f4e035ea6d4c38684c4abc43d91dbf5b46dc6/packages/react-native-gesture-handler/src/handlers/gestures/GestureDetector/index.tsx#L152-L168 ``` attachHandler 1 dropHandler 1 ``` I think the screen might get frozen instead of unmounted, but not entirely sure, but the cleanup function gets called and the handler gets dropped. Now, when reopening the screen the handlers will reattach, but have a different handler tag now. ``` attachHandler 1 dropHandler 1 attachHandler 2 ``` When I now run the gesture I can see that the `manager` still has the **previous handler tag**, and thus on the native side it can't find the handler to activate. Its calling `setGestureHandlerState(1 /* previous id */)` here (when I call `manager.activate`): https://github.com/software-mansion/react-native-gesture-handler/blob/1e1f4e035ea6d4c38684c4abc43d91dbf5b46dc6/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt#L108 I found that attaching the handler tag to the GestureStateMangaer and recreating it if it has changed fixes the issue. If you need a full reproduction to proceed with this change I can understand, just let me know then I can try to find time to create one 👍 ## Test plan <!-- Describe how did you test this change here. --> Well, shamefully I didn't create a reproduction so I guess the test plan is "trust me bro" 😅 not the best I know - sorry. --------- Co-authored-by: Michał Bert <63123542+m-bert@users.noreply.github.com> Co-authored-by: Michał <michal.bert@swmansion.com>
1 parent 71f53c3 commit ae25b49

3 files changed

Lines changed: 10 additions & 1 deletion

File tree

packages/react-native-gesture-handler/src/handlers/gestures/GestureDetector/useAnimatedGesture.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,10 @@ export function useAnimatedGesture(
163163
runWorklet(CALLBACK_TYPE.FINALIZE, gesture, event, false);
164164
}
165165
} else if (isTouchEvent(event)) {
166-
if (!stateControllers[i]) {
166+
if (
167+
!stateControllers[i] ||
168+
stateControllers[i].handlerTag !== event.handlerTag
169+
) {
167170
stateControllers[i] = GestureStateManager.create(event.handlerTag);
168171
}
169172

packages/react-native-gesture-handler/src/handlers/gestures/gestureStateManager.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ export interface GestureStateManagerType {
77
activate: () => void;
88
fail: () => void;
99
end: () => void;
10+
/** @internal */
11+
handlerTag: number;
1012
}
1113

1214
const warningMessage = tagMessage(
@@ -21,6 +23,8 @@ const setGestureState = Reanimated?.setGestureState;
2123
function create(handlerTag: number): GestureStateManagerType {
2224
'worklet';
2325
return {
26+
handlerTag,
27+
2428
begin: () => {
2529
'worklet';
2630
if (REANIMATED_AVAILABLE) {

packages/react-native-gesture-handler/src/handlers/gestures/gestureStateManager.web.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { GestureStateManagerType } from './gestureStateManager';
44
export const GestureStateManager = {
55
create(handlerTag: number): GestureStateManagerType {
66
return {
7+
handlerTag,
8+
79
begin: () => {
810
NodeManager.getHandler(handlerTag).begin();
911
},

0 commit comments

Comments
 (0)