'use Effect is repeating lottie animation

Learning React here, and I'm simply trying to display a lottie animation. Seems fairly straight-forward, but I'm having some trouble with the useEffect hook. I'm using the hook to render the animation on page load, but it keeps repeating itself (sometimes twice or more). I know this is because useEffect will fire more than once, but I'm not sure how to handle this. I just want one animation on the page. How can I achieve this?

import React, { useEffect, useRef } from "react";
import "./index.scss";
import lottie from "lottie-web";

const Hero = () => {
  const lottieContainer = useRef(null);

  useEffect(() => {
    lottie.loadAnimation({
      container: lottieContainer.current,
      renderer: "svg",
      loop: true,
      autoplay: true,
      animationData: require("../../assets/Lottie/developer.json"),
    });
  }, []);


  return (
    <div className="hero">
      <div ref={lottieContainer}></div>
    </div>
  );
};

export default Hero;


Solution 1:[1]

It's because of React strict mode, it tries to help you to detect unwanted side effects and runs all useEffect hooks twice, so you could see that you forgot something. And in that case you forgot to add cleanup function, without it lottie creates 2 animations without cleaning up the first one. Just add this to your code:

  useEffect(() => {
    const instance = lottie.loadAnimation({
      container: document.getElementById('lottie'),
      renderer: 'svg',
      loop: true,
      autoplay: true,
      animationData: require('../../../assets/Lottie/developer.json')
    });

    // Return clean up function here
    return () => instance.destroy();
  }, []);

Codesandbox

Solution 2:[2]

useEffect method as you have write it will execute the inside function when your component is mounted, your useEffect is ok, your lottie config object has a loop property that repeat your animation. You should replace by

lottie.loadAnimation({
      container: lottieContainer.current,
      renderer: "svg",
      loop: false, //or delete this line
      autoplay: true,
      animationData: require("../../assets/Lottie/developer.json"),
});

Solution 3:[3]

import React, { useEffect, useRef } from "react"; import "./index.scss"; import lottie from "lottie-web";

const Hero = () => { const lottieContainer = useRef(null);

useEffect(() => { constinstance = lottie.loadAnimation({ container: lottieContainer.current, renderer: "svg", loop: true, autoplay: true, animationData: require("../../assets/Lottie/developer.json"), }); return () => instance.destroy(); }, []);

return ( ); };

export default Hero;

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 Danila
Solution 2 enzou
Solution 3 Emranul Farhad