react-native-draggable-flatlist icon indicating copy to clipboard operation
react-native-draggable-flatlist copied to clipboard

Anomalies with the list items when multiple drag events occur in a short span

Open maroparo opened this issue 2 years ago • 5 comments

Hello! 👋 First of all, thanks for this wonderful package! 🙌

Describe the bug There seems to be an issue when you make multiple drag actions really quickly. Nothing happens since its not registered as a long press, but then when you press one of the items (supposedly) the item which was touched first flies to where the drag ended. In some cases the drag end won't fire at all and the item stands suspended, until you press on it, in which case it resumes its position. Not 100% sure if that is the actual case but thats what I gathered after a few tries.

To Reproduce This is actually happening on the example snack in the Basic screen so probably I don't need to fill in Platform & Dependencies below.
To reproduce:

  • Shorten the amount of items in the list so there is no need for it to be scrollable (or disable scrolling, also not sure if it has anything to do but I've set bounces={false})
  • Trigger a few drag events on the list (not long presses, just drags) really fast
  • Then press a random item in the list
  • Then an item will snap into a certain position and sometimes it gets stuck there (until you click on it). Also this suppresses other events on the list.

Here is a recording of it:

https://github.com/computerjazz/react-native-draggable-flatlist/assets/27883470/30ba792a-b82e-4e78-870a-0990441ee406

maroparo avatar Sep 22 '23 15:09 maroparo

I'm facing the same issue.

trungledangAxonActive avatar Oct 03 '23 06:10 trungledangAxonActive

I'm facing the same issue.

me too

ilyazonov avatar Oct 05 '23 18:10 ilyazonov

@computerjazz also just found out that this is causing issues when scrolling the list which makes makes it hard to use 😕

maroparo avatar Oct 09 '23 17:10 maroparo

I think the issue comes from this line in DraggableFlatList.tsx :

const panGesture = Gesture.Pan()
    .onBegin((evt) => {
      gestureDisabled.value = disabled.value;
      if (disabled.value) return;
      panGestureState.value = evt.state;
    })
    .onUpdate((evt) => {
      if (disabled.value) return;
      panGestureState.value = evt.state;
      const translation = horizontalAnim.value
        ? evt.translationX
        : evt.translationY;
      touchTranslate.value = translation;
    })
    .onEnd((evt) => {
      if (disabled.value) return;
      // Set touch val to current translate val
      isTouchActiveNative.value = false;
      const translation = horizontalAnim.value
        ? evt.translationX
        : evt.translationY;

      touchTranslate.value = translation + autoScrollDistance.value;
      panGestureState.value = evt.state;

      // Only call onDragEnd if actually dragging a cell
      if (activeIndexAnim.value === -1 || disabled.value) return;
      disabled.value = true;
      runOnJS(onRelease)(activeIndexAnim.value);
      const springTo = placeholderOffset.value - activeCellOffset.value;
      touchTranslate.value = withSpring(
        springTo,
        animationConfigRef.current,
        () => {
          runOnJS(onDragEnd)({
            from: activeIndexAnim.value,
            to: spacerIndexAnim.value,
          });
          disabled.value = false;
        }
      );
    })

The touchTranslate.value is still updated even though no Drag is occuring. I managed to fix it using patch-package :

diff --git a/node_modules/react-native-draggable-flatlist/src/components/DraggableFlatList.tsx b/node_modules/react-native-draggable-flatlist/src/components/DraggableFlatList.tsx
index d7d98c2..f9faaf7 100644
--- a/node_modules/react-native-draggable-flatlist/src/components/DraggableFlatList.tsx
+++ b/node_modules/react-native-draggable-flatlist/src/components/DraggableFlatList.tsx
@@ -266,11 +266,11 @@ function DraggableFlatListInner<T>(props: DraggableFlatListProps<T>) {
   const panGesture = Gesture.Pan()
     .onBegin((evt) => {
       gestureDisabled.value = disabled.value;
-      if (gestureDisabled.value) return;
+      if (activeIndexAnim.value === -1 || disabled.value) return;
       panGestureState.value = evt.state;
     })
     .onUpdate((evt) => {
-      if (gestureDisabled.value) return;
+      if (activeIndexAnim.value === -1 || disabled.value) return;
       panGestureState.value = evt.state;
       const translation = horizontalAnim.value
         ? evt.translationX
@@ -278,7 +278,7 @@ function DraggableFlatListInner<T>(props: DraggableFlatListProps<T>) {
       touchTranslate.value = translation;
     })
     .onEnd((evt) => {
-      if (gestureDisabled.value) return;
+      if (activeIndexAnim.value === -1 || disabled.value) return;
       // Set touch val to current translate val
       isTouchActiveNative.value = false;
       const translation = horizontalAnim.value

I'm not sure about side effects though.

Maniae avatar Dec 07 '23 17:12 Maniae

@Maniae seems to work. Can't notice any side effect either. Might be worth opening a PR 🚀

maroparo avatar Dec 14 '23 22:12 maroparo