'How I can start animation after stop animation in React Native?

I have a component in which the animation takes place. when the button is pressed, the value changes isPaused and then the animation either stops or starts. But for some reason, after the stop, when I click on the button and the value of the variable changes in the state, other scripts are launched and work as needed, and the animation continues to be paused

const anim = useMemo(() => {
    return Animated.loop(
        Animated.sequence([
            Animated.timing(figureScale, { toValue: 2, duration: animSpeed, useNativeDriver: true}),
            Animated.timing(figureScale, { toValue: 1, duration: animSpeed, useNativeDriver: true})
        ])
    )
  }, [figureScale])



  useEffect(()=>{
      let _localAnim = anim
      if(isPaused) {
        _localAnim.stop()
      } else {
        _localAnim.start() 
      }
        
  }, [isPaused])


Solution 1:[1]

UPDATED

Animations stopped cannot be restarted so you should not memoize them but recreate at each render (function call)

Following your approach:

const [isPaused, setPause] = useState(true)

const figureScale = useRef(new Animated.Value(1)).current

useEffect(()=> isPaused ? anim.stop() : anim.start() , [isPaused, anim])

const anim = Animated.loop(
    Animated.sequence([
        Animated.timing(figureScale, { toValue: 2, duration: 500, useNativeDriver: true}),
        Animated.timing(figureScale, { toValue: 1, duration: 500, useNativeDriver: true})
    ])
  )

Still there is a problem because even though we keep the Animated.Value in the ref, the sequence restart using the first Animated.timing (expanding) also when we stop during the second one (decreasing).

I tried to solve with interpolation with no success but a solution I found it's to add a listener to the Animated.Value and save the expanding/decreasing state in a variable (state or closure).
( https://reactnative.dev/docs/animatedvalue#addlistener )

Using the state (extra rendering):

const [isGrowing, setGrowing] = useState(true)
  
figureScale.addListener(({value})=>{
  if(isGrowing && value==2) {setGrowing(false)}
  if(!isGrowing && value==1) {setGrowing(true)}
 })
  

Using a closure:

const isGrowing = React.useMemo(() =>
  {
    // static variable
    let _isGrowing = true
    // returned function
    return function(growing){
      if(growing===1) _isGrowing = true
      if(growing===-1) _isGrowing = false
      return _isGrowing
    }
  }, [] )

figureScale.addListener(({value})=>{
    if(isGrowing() && value==2) {isGrowing(-1)}
    if(!isGrowing() && value==1) {isGrowing(1)}
  })

Finally we can choose the order of the animations inside the sequence following the expanding/decreasing stop:

Using the state:

const anim = Animated.loop(
Animated.sequence([
    Animated.timing(figureScale, { toValue: isGrowing ?2:1, duration: 500, useNativeDriver: true}),
    Animated.timing(figureScale, { toValue: isGrowing ?1:2, duration: 500, useNativeDriver: true})
])

)

Using a closure:

 const anim = Animated.loop(
    Animated.sequence([
        Animated.timing(figureScale, { toValue: isGrowing() ?2:1, duration: 500, useNativeDriver: true}),
        Animated.timing(figureScale, { toValue: isGrowing() ?1:2, duration: 500, useNativeDriver: true})
    ])
  )

Working example here: https://snack.expo.dev/@laxandrea/start-stop-animations

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1