Tim
Tim

Reputation: 10709

useEffect reverse animation is not shown

Problem:

Currently, I am struggling with the useEffect Hook together with Animated.timing. Somehow the reverse animation is not shown. The toggle just jumps back (see gif below). Confusingly, the animation callback is successfully called.

Wanted behavior: The slider should animate back and forth smoothly, when the active prop is changed.

Animation

Code

Slider:

const Slider = ({sliderWidth, circleHeight, active, onToggle}) => {
    const transformX = new Animated.Value(0);

    React.useEffect(() => {
      console.log('only run when active changed', transformX);
      const value = active ? sliderWidth-circleHeight: 0;
      console.log('value', value);
        Animated.timing(transformX, {
          toValue: value,
          duration: 500,
          useNativeDriver: true
        }).start(() => console.log('animation done'));
    }, [active, transformX, sliderWidth, circleHeight]);

    return (
      <View style={{position: 'absolute',width: sliderWidth+10, backgroundColor: 'white', borderBottomLeftRadius: 8, borderBottomRightRadius: 8, flexDirection: 'column', alignItems: 'center'}}>
        <View style={{width: sliderWidth, borderRadius: sliderWidth/2, borderWidth: 1, height: circleHeight,justifyContent: 'center', alignItems: 'center', marginTop: 8, marginBottom: 8, backgroundColor: 'white'}}>
          <Text style={{fontSize: 11}}> {active ?  "Pickup" : "Delivery"} </Text>
          <TouchableOpacity onPress={onToggle} style={{position: 'absolute', left:0,  transform: [{translateX: transformX}]}}>
          <View style={{height: circleHeight-2, width: circleHeight-2, borderRadius: circleHeight/2-1, backgroundColor: 'orange' }} />
          </TouchableOpacity>
        </View>
      </View>
    );
};

App:

export default function App() {
  const sliderWidth = WIDTH/3;
  const circleHeight = 30;
  const [active, setActive] = React.useState(0);
  return (
    <View style={styles.container}>
      <Slider sliderWidth={sliderWidth} circleHeight={circleHeight} onToggle={() => setActive(!active)} active={active}/>
    </View>
  );
}

Snack

https://snack.expo.io/@tim1717/useeffect-animation

Upvotes: 0

Views: 698

Answers (1)

Ian Vasco
Ian Vasco

Reputation: 1340

This is really simple, you shall use transformX as state instead. Honestly, I don't know what causes the issue but this is a problem there.

const Slider = ({sliderWidth, circleHeight, active, onToggle}) => {
  const [transformX] = React.useState(new Animated.Value(0));
...

Upvotes: 2

Related Questions