React-native-reanimated: isCancelled receive wrong value

Created on 5 Sep 2020  ·  2Comments  ·  Source: software-mansion/react-native-reanimated

Description

withTiming, withSpring & withDecay callbacks method has a isCancelled parameter which comes negative all the time.

Screenshots

ezgif-6-40fffc73c46d

Steps To Reproduce

  1. start any of withTiming, withSpring & withDecay animations and pass a callback method.
  2. before the animation ends, cancel it
  3. the callback method will be fired with isCancelled is false!
  4. repeat step 1
  5. let the animation end
  6. the callback method will be fired with isCancelled is true!

Expected behavior

isCancelled to represent its value.

Actual behavior

isCancelled is return true when animation is complete, but false when animation been cancelled.

Snack or minimal code example

import React from 'react';
import { StyleSheet } from 'react-native';
import { PanGestureHandler } from 'react-native-gesture-handler';
import Animated, {
  useAnimatedGestureHandler,
  useAnimatedStyle,
  cancelAnimation,
  useSharedValue,
  withTiming,
} from 'react-native-reanimated';

const App = () => {
  const x = useSharedValue(0);
  const y = useSharedValue(0);

  const handleAnimationCompletion = (isCancelled: boolean) => {
    console.log('handleAnimationCompletion', `isCancelled: ${isCancelled}`);
  };

  const handleGestureEvent = useAnimatedGestureHandler({
    onStart: (_, context) => {
      cancelAnimation(x);
      cancelAnimation(y);
      context.translationX = x.value;
      context.translationY = y.value;
    },
    onActive: ({ translationX, translationY }, context) => {
      x.value = translationX + context.translationX;
      y.value = translationY + context.translationY;
    },
    onEnd: () => {
      x.value = withTiming(0, {
        duration: 1000,
      });
      y.value = withTiming(
        0,
        {
          duration: 1000,
        },
        handleAnimationCompletion
      );
    },
  });

  const boxAnimatedStyle = useAnimatedStyle(() => {
    return {
      transform: [
        {
          translateX: x.value,
        },
        {
          translateY: y.value,
        },
      ],
    };
  });
  return (
    <PanGestureHandler onGestureEvent={handleGestureEvent}>
      <Animated.View style={styles.container}>
        <Animated.View style={[styles.box, boxAnimatedStyle]} />
      </Animated.View>
    </PanGestureHandler>
  );
};

export default App;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 24,
    alignContent: 'center',
    justifyContent: 'center',
    alignItems: 'center',
  },
  box: {
    width: 100,
    height: 100,
    backgroundColor: 'red',
  },
});

Package versions

  • React: 16.13.1
  • React Native: 0.63.2
  • React Native Reanimated: 2.0.0-alpha.5
  • React Native Gesture Handler: 1.7.0
🏠 Reanimated2 🐞 Bug

Most helpful comment

The problem is with typescript typings where isCanceled is used instead.

All 2 comments

As stated in the docs:

Callback is run with a single argument – a boolean indicating whether the animation has finished executing without cancellation

The argument is finished, not isCancelled. That name appears in a several places in the code.
Plus if you really need isCancelled feel free to use negation, it could look like this:

function callback(finished) {
    const isCancelled = !finished;
    // ...
}

The problem is with typescript typings where isCanceled is used instead.

Was this page helpful?
0 / 5 - 0 ratings