Skip to content

Fix state manager on unregistered gestures#3913

Merged
akwasniewski merged 10 commits intonextfrom
@akwasniewski/fix-android-state-manager
Jan 30, 2026
Merged

Fix state manager on unregistered gestures#3913
akwasniewski merged 10 commits intonextfrom
@akwasniewski/fix-android-state-manager

Conversation

@akwasniewski
Copy link
Copy Markdown
Contributor

@akwasniewski akwasniewski commented Jan 9, 2026

Description

The new StateManager is global and given handlerTag it can manually set the states of an arbitrary gesture. This causes errors, when the gesture, which state is being set, has not been yet recorded in the orchestrator. Recording gestures in the orchestrator on android is done lazily, thus if it never received touches it is not recorded.

It also adds explicit error when trying to manually handled a gesture not attached to any detector on all platforms.

Test plan

Tested on the following example

Details
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { GestureHandlerRootView, GestureDetector, useLongPressGesture, GestureStateManager, usePanGesture, useSimultaneousGestures, useTapGesture } from 'react-native-gesture-handler';

export default function TwoPressables() {
  const longPress = useLongPressGesture({
    onTouchesDown: (e) => {
      'worklet';
      console.log("touches down")
    },
    onActivate: () => {
      'worklet';
      console.log("long pressed")
    },
    minDuration: 100000000,
    disableReanimated: true
  })
  const pan = useTapGesture({
    onTouchesDown: () => {
      'worklet';
      console.log("tap")

      GestureStateManager.activate(longPress.tag)
    },
    disableReanimated: true
  });
  return (
    <GestureHandlerRootView>
      <View style={styles.root}>
        <GestureDetector gesture={longPress}>
          <View style={styles.outer}>
            <Text style={styles.label}>Long Press</Text>
          </View>
        </GestureDetector>
        <GestureDetector gesture={pan}>
          <View style={styles.outer}>
            <Text style={styles.label}>Pan</Text>
          </View>
        </GestureDetector>

      </View>
    </GestureHandlerRootView>
  );
}

const styles = StyleSheet.create({
  root: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f7f7f7',
  },
  outer: {
    padding: 20,
    backgroundColor: '#ddd',
    borderRadius: 12,
    marginBottom: 50
  },
  label: {
    fontSize: 18,
    marginBottom: 10,
  },
})

@akwasniewski akwasniewski requested a review from m-bert January 9, 2026 13:32
@akwasniewski akwasniewski changed the base branch from main to next January 9, 2026 13:32
Copy link
Copy Markdown
Collaborator

@m-bert m-bert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As said in the first comment, I'm not a big fan of ForManual suffix. I think we could either use overloading (where possible) or add more descriptive suffix.

Andrzej Antoni Kwaśniewski added 2 commits January 13, 2026 08:22
Comment on lines +210 to +222
private fun findGestureHandlerRootView(): RNGestureHandlerRootView? {
var parent: ViewParent? = this.parent
var gestureHandlerRootView: RNGestureHandlerRootView? = null

while (parent != null) {
if (parent is RNGestureHandlerRootView) {
gestureHandlerRootView = parent
}
parent = parent.parent
}

return gestureHandlerRootView
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we have this exact method already defined somewhere? Maybe it's worth moving it to some utils, or making it an extension on View?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I moved it to be companion object for the rootView in 8a4ffc9. Let me know what you think.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm not sure whether this.findGestureHandlerRootView()?... wouldn't have been cleaner, but I'll leave the final decision to you. Both work for me.

@akwasniewski akwasniewski changed the title [android] Fix state manager on unregistered gestures Fix state manager on unregistered gestures Jan 29, 2026
@akwasniewski akwasniewski merged commit d519ea3 into next Jan 30, 2026
8 checks passed
@akwasniewski akwasniewski deleted the @akwasniewski/fix-android-state-manager branch January 30, 2026 07:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants