Skip to content
Advertisement

React Native Lottie Animation Only Plays On First Tap

So essentially, I want to play the lottie animation everytime it is tapped. Here is my UI code for the lottie animation:

<Pressable onPress={playGame}>

<LottieView
   ref={loseAnimationRef}
   style={styles.egg}
   source={Lost}
   autoPlay={false}
   loop={false}
   onAnimationFinish={() => {
      resetAnimation();
   }}
/>

</Pressable>

Here is my state code for the lottie animation:

  const loseAnimationRef = useRef(null);

  const playGame = async () => {
    await mainGameLogicUC();
    playAnimation()
  };

  const playAnimation = () => {
      loseAnimationRef.current.play()
  }

  const resetAnimation = () => {
      loseAnimationRef.current.reset()
  }

On the first tap, the animation play perfefctly fine. But on all other taps, the animation won’t play. I tried pausing the animation in the onAnimationFinish and then resuming it, but that also didn’t work. Am I missing something?

EDIT

I got rid of the resetAnimation() in the onAnimationFinish and that solved the initial problem. But the thing is, I want the animation to be reset to the beginning every time. Why does it break when I reset the animation?

Answer

After coming back to this problem a few days later, I found the solution

Playing the lottie animation seems to be considered a side effect, therefore, editing the references to the animations should be done in a useEffect hook

The solution that worked for me:

(again, in this code, I want the animation to reset to the beginning before the user taps the screen screen again.

state code

  const isMounted = useRef(false);

  const [isWonAnimationShowing, setIsWonAnimationShowing] = useState(false);
  const [isAnimationPlaying, setIsAnimationPlaying] = useState(false);
  const loseAnimationRef = useRef(null);
  const winAnimationRef = useRef(null);

  useEffect(() => {
    if (isMounted.current) {
      if (isAnimationPlaying) {
        _playAnimation();
      } else {
        _resetAnimation();
      }
    } else {
      isMounted.current = true;
    }
  }, [isAnimationPlaying]);


  const playAnimation = () => {
    setIsAnimationPlaying(true);
  };


  const _playAnimation = () => {
    if (isWonAnimationShowing) {
      winAnimationRef.current.play();
    } else {
      loseAnimationRef.current.play();
    }
  };


  const resetAnimation = () => {
    setIsAnimationPlaying(false);
  };


  const _resetAnimation = () => {
    if (isWonAnimationShowing) {
      winAnimationRef.current.reset();
    } else {
      loseAnimationRef.current.reset();
    }
  };

UI code

    <View style={styles.body}>
      <Pressable disabled={isAnimationPlaying} onPress={playGame}>
        {isWonAnimationShowing ? (
          <LottieView
            ref={winAnimationRef}
            style={styles.egg}
            source={Won}
            autoPlay={false}
            loop={false}
            onAnimationFinish={() => {
              resetAnimation();
            }}
          />
        ) : (
          <LottieView
            ref={loseAnimationRef}
            style={styles.egg}
            source={Lost}
            autoPlay={false}
            loop={false}
            onAnimationFinish={() => {
              resetAnimation();
            }}
          />
        )}
      </Pressable>
    </View>
Advertisement