software-mansion / react-native-gesture-handler

Declarative API exposing platform native touch and gesture system to React Native.
https://docs.swmansion.com/react-native-gesture-handler/
MIT License
6.12k stars 980 forks source link

Race GestureDetector and ScrollView #2496

Closed AlexLup06 closed 1 year ago

AlexLup06 commented 1 year ago

Description

I want to Race a PanGesture and the ScrollView. It used to work by setting the SimultaneousHandlers prop of the PanGestureHandler with the ref of the ScrollView.

With the new API i do: Gesture.Race(swipeGesture,scrollViewRef) and get this error

TypeError: gesture.toGestureArray is not a function. (In 'gesture.toGestureArray()', 'gesture.toGestureArray' is undefined)

I want only the ScrollView or only the SwipeToDelete to fire

The Code looks like this:

Home.tsx

import { useRef } from "react";
import { View } from "react-native";
import { ScrollView } from "react-native-gesture-handler";
import Swipe from "../../lib/components/SwipeToDelete";

export default function Profile() {
  const scrollViewRef = useRef();
  return (
    <View style={{ margin: 20 }}>
      <ScrollView style={{ height: 1000 }} ref={scrollViewRef}>
        <SwipeToDelete simultaneousRef={scrollViewRef} />
      </ScrollView>
    </View>
  );
}

SwipeToDelete.tsx

import { Gesture, GestureDetector } from "react-native-gesture-handler";
import Animated, {
  useAnimatedStyle,
  useSharedValue,
  withTiming,
} from "react-native-reanimated";

export default function SwipeToDelete({ simultaneousRef }) {
  const transX = useSharedValue(0);
  const leftOn = useSharedValue(false);

  const swipeGesture = Gesture.Pan()
        // Simply setting transX.value. This works
    });

  const race = Gesture.Race(swipeGesture, simultaneousRef);

  const animatedStyle = useAnimatedStyle(() => {
    return {
      transform: [{ translateX: transX.value }],
    };
  });

  return (
      <GestureDetector gesture={race}>
        <Animated.View style={ animatedStyle} >
          <Text>Swipe to see</Text>
        </Animated.View>
      </GestureDetector>
  );
}

Steps to reproduce

  1. Check out the Snack Example

Snack or a link to a repository

https://snack.expo.dev/@alex_lup/ashamed-strawberries?platform=ios

Gesture Handler version

2.9

React Native version

0.71.6

Platforms

iOS

JavaScript runtime

None

Workflow

None

Architecture

None

Build type

None

Device

None

Device model

No response

Acknowledgements

Yes

j-piasecki commented 1 year ago

Race, Simultaneous and Exclusive only work when you pass the gesture config objects to them (and not the ref), and they attach all the gestures to the underlying view, which would be undesirable in your case.

I want to Race a PanGesture and the ScrollView. It used to work by setting the SimultaneousHandlers prop of the PanGestureHandler with the ref of the ScrollView.

The simultaneousHandlers behaves the same as Gesture.Simultaneous not Gesture.Race. If you want only one of the gesture to be active at the same time, you don't need to set any relations between them as that's the default behavior.

If you want them to be simultaneous, you can use .simultaneousWithExternalGesture(ref) modifier on the pan gesture.

AlexLup06 commented 1 year ago

@j-piasecki Thanks you for your answer! But now I am trying to build my own Swipeable component but can't get it to figure out how to make it work inside a ScrollView. Could you maybe give me a hint on how your Swipeable works. Or maybe even explain it. I posted a full question in the discussion section to clarify more :)

https://github.com/software-mansion/react-native-gesture-handler/discussions/2501

j-piasecki commented 1 year ago

Ok, in that case, I'll close the issue, and let's move the discussion to the discussion 😅.