react-lottie
react-lottie copied to clipboard
This library is no longer maintained. Making your own simple wrapper isn't difficult...
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>
}
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
Thanks a lot, this works great for most use-cases and is much cleaner.
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'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]);
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;
}, []);
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])
hi,
just a heads up this will leak your instances as it's not actually calling destroy on
lottieInstance.current
. I'd add something likeReact.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.
@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 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.