use Effect is repeating lottie animation
Asked Answered
A

3

5

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;
Arbela answered 27/4, 2022 at 15:49 Comment(2)
Maybe you could make a quick reproduction on codesandbox.io?Repression
codesandbox.io/s/animated-section-szzl1p?file=/src/index.jsArbela
R
8

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

Repression answered 28/4, 2022 at 18:27 Comment(0)
A
0

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"),
});
Assuntaassur answered 27/4, 2022 at 18:46 Comment(3)
This is likely it, the useEffect is fine.Spondylitis
I thought that too initially, but it keeps happening - even if I remove the loop property.Arbela
Also, the loop property only loops the animation. Which is what I want. I don't think that would cause it to duplicate itself.Arbela
F
0

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;

Fizz answered 14/5, 2022 at 12:29 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Gibbet

© 2022 - 2024 — McMap. All rights reserved.