React-native-reanimated: withTiming callback function is called multiple times

Created on 17 Sep 2020  路  1Comment  路  Source: software-mansion/react-native-reanimated

Description

Short: If duration is 250 or similar value - withTiming callback is called multiple times. That breaks animation.

I use withTiming to detect when animation is finished. And if animation is completed successfully I call callback _onSwipeRight.

  const containerStyle = useAnimatedStyle(() => {
    return {
      height:
        rowHeight.value !== undefined
          ? withTiming(
              rowHeight.value,
              {
                duration: 250,
                easing: Easing.out(Easing.ease)
              },
              (isFinished) => {
                console.log(`withTiming is finished? ${isFinished}`);
                if (isFinished) {
                  if (swipeDirection.value === 'left') {
                    onSwipeLeft();
                  } else if (swipeDirection.value === 'right') {
                    console.log(
                      `SwipableRow: isFinished? ${isFinished}, rowHeight: ${rowHeight.value}`
                    );
                    _onSwipeRight && _onSwipeRight();
                  }
                }
              }
            )
          : undefined
    };
  });

Later inside this _onSwipeRight() I update sqlite database (mark task as _completed_) and unmount component (render undefined instead of task - at this time height of row should be 0)

  const [isVisible, setVisible] = useState(true);
  const onTaskCompletion = useCallbackOne(
    (id: string) => {
      console.log(`[onTaskCompletion] complete task ${id}`);
      taskRepository.update(id, { isCompleted: true }).then((_) => {
        setVisible(false);
      });
    },
    [taskRepository]
  );
  ...
  return (
    <>
      {isVisible ? (
        <SwipableTask
          id={state.id}
          title={state.title}
          isCompleted={state.isCompleted}
          isTracked={state.isTracked}
          trackedSeconds={state.trackedSeconds}
          onCompletionButtonPressed={onCompletionButtonPressed}
          onTrackButtonPressed={onTrackButtonPressed}
          onCompletionSwipe={onTaskCompletion}
        />
      ) : undefined}
    </>
  );

If I use duration 150 or 300 for withTiming I see expected behaviour and logging. But for 250 milliseconds

[Thu Sep 17 2020 15:19:49.708]  LOG      withTiming is finished? true // <-- First call
[Thu Sep 17 2020 15:19:49.710]  LOG      SwipableRow: isFinished? true, rowHeight: 0
[Thu Sep 17 2020 15:19:49.710]  LOG      [onTaskCompletion] complete task f2dcb1fa-7531-4b1e-a63c-dbf713589c22
[Thu Sep 17 2020 15:19:49.711]  INFO     query:  UPDATE "tasks" SET "isCompleted" = ? WHERE "id" IN (?) -- PARAMETERS: [1,"f2dcb1fa-7531-4b1e-a63c-dbf713589c22"]
[Thu Sep 17 2020 15:19:49.729]  LOG      Row: isVisible? false, id [f2dcb1fa-7531-4b1e-a63c-dbf713589c22], title [Task 11]
[Thu Sep 17 2020 15:19:49.987]  LOG      withTiming is finished? true // <-- Second call
[Thu Sep 17 2020 15:19:49.989]  LOG      SwipableRow: isFinished? true, rowHeight: 0
[Thu Sep 17 2020 15:19:49.990]  LOG      [onTaskCompletion] complete task f2dcb1fa-7531-4b1e-a63c-dbf713589c22
[Thu Sep 17 2020 15:19:49.991]  INFO     query:  UPDATE "tasks" SET "isCompleted" = ? WHERE "id" IN (?) -- PARAMETERS: [1,"f2dcb1fa-7531-4b1e-a63c-dbf713589c22"]
[Thu Sep 17 2020 15:19:49.997]  LOG      Row: isVisible? false, id [f2dcb1fa-7531-4b1e-a63c-dbf713589c22], title [Task 11]

Screenshots

250 ms 300 ms 150 ms

Expected behavior

Callback is called only once.

Actual behavior

Callback might be called multiple times.

Snack or minimal code example

Package versions

  • React: 16.11.0
  • React Native: 0.62.2
  • React Native Reanimated: 2.0.0-alpha.6
馃彔 Reanimated2 馃悶 Bug

Most helpful comment

Hey @likern
Thanks for your report. It was a bug but this issue is resolved in a newer release. if you still have a problem try a newer version of reanimated. I tested this on alpha.9 and it works.

>All comments

Hey @likern
Thanks for your report. It was a bug but this issue is resolved in a newer release. if you still have a problem try a newer version of reanimated. I tested this on alpha.9 and it works.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nextriot picture nextriot  路  3Comments

colinux picture colinux  路  3Comments

alexfov picture alexfov  路  3Comments

ArsalanCsquare picture ArsalanCsquare  路  3Comments

levibuzolic picture levibuzolic  路  3Comments