javascriptreact-nativereact-animated

React Native Animated setValue() problem?


Actually I'm trying to set value of the animation with setValue() after Animated.timing() is finished and want to use this updated animated value then in a loop animation.

//Initialising animation value=50
const leftAnim = useRef(new Animated.Value(50)).current 
useEffect(() => {
    Animated.timing(leftAnim,{
        toValue:360,
        duration:3000,
        easing:Easing.linear,
        useNativeDriver:false,
    }).start(({finished}) => {
        //Updating animation value=100
        leftAnim.setValue(100)
        //Animated API is not considering the setValue and starting the loop animation with the first value i.e 50 instead of 100
        Animated.loop(
            Animated.timing(leftAnim,{
                toValue:360,
                duration:5000,
                easing:Easing.linear,
                useNativeDriver:false
            })
        ).start()
    })
},[])

Am I doing something wrong? Is there a better way to do it?


Solution

  • You can use leftAnim.setOffset(nextStart) and inside loop adjust end accordingly. Demo on snack expo

    import React, { Component, useRef, useEffect, useState } from 'react';
    import { Easing, StyleSheet, View, Animated, Button, Text } from 'react-native';
    
    const start = 0;
    const end = 100;
    
    export default Anim = () => {
      const leftAnim = useRef(new Animated.Value(start)).current;
      const [curValue, setCurValue] = useState(start);
    
      useEffect(() => {
        leftAnim.addListener((v) => {
          setCurValue(v.value.toFixed(0));
        });
    
        Animated.timing(leftAnim, {
          toValue: end,
          duration: 5000,
          easing: Easing.linear,
          useNativeDriver: false,
        }).start(({ finished }) => {
          //setting value to 80
          leftAnim.setOffset(80);
    
          // increment only by 20, 80 + 20 = 100
          Animated.loop(
            Animated.timing(leftAnim, {
              toValue: end - 80,
              duration: 2000,
              easing: Easing.linear,
              useNativeDriver: false,
            })
          ).start();
        });
      }, [leftAnim]);
      return (
        <View style={styles.container}>
          <Animated.Image
            source={require('./assets/snack-icon.png')}
            style={{ width: 40, height: 40, transform: [{ translateY: leftAnim }] }}
          />
    
          <Text>Current Value: {curValue}</Text>
        </View>
      );
    };
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'start',
        alignItems: 'center',
        padding: 10,
        paddingTop: 50,
      },
      input: {
        height: 50,
        marginHorizontal: 15,
        backgroundColor: '#ededed',
        marginTop: 10,
        paddingHorizontal: 9,
      },
    });