Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

This library is no longer maintained. Making your own simple wrapper isn't difficult... #139

Open
funwithtriangles opened this issue Jan 26, 2022 · 9 comments

Comments

@funwithtriangles
Copy link

funwithtriangles commented Jan 26, 2022

If you need something complex, then react-lottie-player looks good. Otherwise the code below is all you need to display a lottie animation on your page. There is no play/pause logic here but that wouldn't be too tricky to add. Just thought I'd post this in case anyone is wondering how much work it will be to get something working themselves.

import { useEffect, useRef } from "react"

import lottie from "lottie-web"

interface LottieProps {
  animationData: any
  width: number
  height: number
}

export const Lottie = ({ animationData, width, height }: LottieProps) => {
  const element = useRef<HTMLDivElement>(null)
  const lottieInstance = useRef<any>()

  useEffect(() => {
    if (element.current) {
      lottieInstance.current = lottie.loadAnimation({
        animationData,
        container: element.current,
      })
    }
    return () => {
      lottieInstance.current?.destroy()
    }
  }, [animationData])

  return <div style={{ width, height }} ref={element}></div>
}
@granolocks
Copy link

I was getting this vibe too. Sad to see since it worked fairly well but this is a nice base for a shim. Thank you @funwithtriangles

@adrian-burkhart
Copy link

Thanks a lot, this works great for most use-cases and is much cleaner.

@lclarkg18
Copy link

I'm getting a weird error with this code whereby the animations load twice, any ideas? All I can think of is it's related to the usage of the dependancy array in the useEffct but no idea. Thanks btw!

@SwTan98
Copy link

SwTan98 commented Jun 15, 2022

I'm getting a weird error with this code whereby the animations load twice, any ideas? All I can think of is it's related to the usage of the dependancy array in the useEffct but no idea. Thanks btw!

I tried updating the useEffect a little bit, seems to work fine now.

useEffect(() => {
    if (element.current) {
      lottie.loadAnimation({
        animationData,
        container: element.current,
      });
    }
  }, [animationData]);

@evertjr
Copy link

evertjr commented Jun 15, 2022

I'm getting a weird error with this code whereby the animations load twice, any ideas? All I can think of is it's related to the usage of the dependancy array in the useEffct but no idea. Thanks btw!

If you're using React 18, useEffect runs twice on mount to make sure the code is idempotent. (only happens in development) And since we are using it to render an animation to the DOM, it explains why this happens.

A workaround is using useRef like this:

const element = useRef(null);
  const lottieInstance = useRef();
  const executeRef = useRef(false);

  useEffect(() => {
    if (executeRef.current) return;
    if (element.current) {
      lottieInstance.current = lottie.loadAnimation({
        animationData,
        loop,
        autoplay,
        container: element.current,
      });
    }
    executeRef.current = true;
  }, []);

@chrisnojima
Copy link

hi,

just a heads up this will leak your instances as it's not actually calling destroy on lottieInstance.current. I'd add something like

  React.useEffect(() => {
    if (element.current) {
      lottieInstance.current?.destroy()
      lottieInstance.current = lottie.loadAnimation({
        animationData,
        container: element.current,
      })
    }
    return () => {
      lottieInstance.current?.destroy()
      lottieInstance.current = null
    }
  }, [animationData])

@funwithtriangles
Copy link
Author

hi,

just a heads up this will leak your instances as it's not actually calling destroy on lottieInstance.current. I'd add something like

  React.useEffect(() => {
    if (element.current) {
      lottieInstance.current?.destroy()
      lottieInstance.current = lottie.loadAnimation({
        animationData,
        container: element.current,
      })
    }
    return () => {
      lottieInstance.current?.destroy()
      lottieInstance.current = null
    }
  }, [animationData])

Good point! I updated my example above. Pretty sure you don't need to have the destroy twice though, the clean up return function will happen before the effect runs every time.

@jordanlambrecht
Copy link

@funwithtriangles Could you help me get segments to work with this? I can't seem to figure it out. I'm trying to get it to play all frames on the first loop, and then only frames 24-95 on every loop thereafter.

Currently, I have:
segments: {[ [0, 23],[24, 95]], true},

@funwithtriangles
Copy link
Author

funwithtriangles commented Aug 9, 2022

@funwithtriangles Could you help me get segments to work with this? I can't seem to figure it out. I'm trying to get it to play all frames on the first loop, and then only frames 24-95 on every loop thereafter.

Currently, I have: segments: {[ [0, 23],[24, 95]], true},

Sorry, I don't know the API very well! I was just posting a simple example that I thought might help others with similar simple needs. If you need anything more complex, then maybe react-lottie-player is more suitable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants