Skip to content

Cleaning manually activated handlers#3943

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

Cleaning manually activated handlers#3943
akwasniewski merged 3 commits intonextfrom
@akwasniewski/fix-state-manager

Conversation

@akwasniewski
Copy link
Copy Markdown
Contributor

@akwasniewski akwasniewski commented Jan 30, 2026

Description

On android and web gestures activated with state manager were not cleaned up properly as they were never registered in the gesture orchestrator.

Test plan

Tested on the following example

Details
import React from 'react';
import { StyleSheet, View } from 'react-native';
import {
  GestureHandlerRootView,
  GestureDetector,
  useLongPressGesture,
  GestureStateManager,
  LongPressGesture,
} from 'react-native-gesture-handler';
import Animated, {
  useAnimatedStyle,
  useSharedValue,
  withTiming,
} from 'react-native-reanimated';

export const COLORS = {
  offWhite: '#f8f9ff',
  headerSeparator: '#eef0ff',
  PURPLE: '#b58df1',
  NAVY: '#001A72',
  RED: '#A41623',
  YELLOW: '#F2AF29',
  GREEN: '#0F956F',
  GRAY: '#ADB1C2',
  KINDA_RED: '#FFB2AD',
  KINDA_YELLOW: '#FFF096',
  KINDA_GREEN: '#C4E7DB',
  KINDA_BLUE: '#A0D5EF',

};
export default function TwoPressables() {
  const isActivated = [
    useSharedValue(0),
    useSharedValue(0),
    useSharedValue(0),
    useSharedValue(0),
  ];
  const gestures: LongPressGesture[] = [];

  const createGestureConfig = (index: number) => ({
    onActivate: () => {
      'worklet';
      isActivated[index].value = 1;
      console.log(`Box ${index}: long pressed`);

      const nextIndex = index + 1;
      if (nextIndex < gestures.length) {
        const nextGesture = gestures[nextIndex];
        if (nextGesture) {
          GestureStateManager.activate(nextGesture.handlerTag);
        }
      }
    },
    onFinalize: () => {
      'worklet';
      isActivated[index].value = 0;
      const nextIndex = index + 1;
      if (nextIndex < gestures.length) {
        const nextGesture = gestures[nextIndex];
        if (nextGesture) {
          GestureStateManager.deactivate(nextGesture.handlerTag);
        }
      }
    },
    disableReanimated: true,
  });

  const g0 = useLongPressGesture(createGestureConfig(0));
  const g1 = useLongPressGesture(createGestureConfig(1));
  const g2 = useLongPressGesture(createGestureConfig(2));
  const g3 = useLongPressGesture(createGestureConfig(3));

  gestures[0] = g0;
  gestures[1] = g1;
  gestures[2] = g2;
  gestures[3] = g3;

  const colors = [COLORS.PURPLE, COLORS.NAVY, COLORS.GREEN, COLORS.RED];

  function Box({ index }: { index: number }) {
    const animatedStyle = useAnimatedStyle(() => ({
      opacity: isActivated[index].value === 1 ? 0.5 : 1,
      transform: [
        { scale: withTiming(isActivated[index].value === 1 ? 0.95 : 1) },
      ],
    }));

    return (
      <GestureDetector gesture={gestures[index]}>
        <Animated.View
          style={[
            commonStyles.box,
            { backgroundColor: colors[index] },
            animatedStyle,
          ]}
        />
      </GestureDetector>
    );
  }
  return (
    <GestureHandlerRootView>
      <View style={commonStyles.centerView}>
        <Box index={0} />
        <Box index={1} />
        <Box index={2} />
        <Box index={3} />
      </View>
    </GestureHandlerRootView>
  );
}
const commonStyles = StyleSheet.create({
  centerView: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  box: {
    height: 150,
    width: 150,
    borderRadius: 20,
    marginBottom: 30,
  },
})

@akwasniewski akwasniewski marked this pull request as draft January 30, 2026 12:59
@akwasniewski akwasniewski changed the title Fix state manager Cleaning manually activated gestures Jan 30, 2026
@akwasniewski akwasniewski changed the title Cleaning manually activated gestures Cleaning manually activated handlers Jan 30, 2026
@akwasniewski akwasniewski marked this pull request as ready for review January 30, 2026 14:24
@akwasniewski akwasniewski merged commit e0e3a91 into next Jan 30, 2026
5 checks passed
@akwasniewski akwasniewski deleted the @akwasniewski/fix-state-manager branch January 30, 2026 14:40
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.

2 participants