computerjazz / react-native-draggable-flatlist

A drag-and-drop-enabled FlatList for React Native
MIT License
1.92k stars 402 forks source link

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

Open maroparo opened 1 year ago

maroparo commented 1 year ago

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:

Here is a recording of it:

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

trungledangAxonActive commented 12 months ago

I'm facing the same issue.

ilyazonov commented 11 months ago

I'm facing the same issue.

me too

maroparo commented 11 months ago

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

Maniae commented 9 months ago

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.

maroparo commented 9 months ago

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