Open theashraf opened 2 months ago
Hey @theashraf ! did you find anything useful?
We have the same issue. We use @lottiefiles/dotlottie-web@^0.34.0
with next@^14.2.13
. (We preferred to use @lottiefiles/dotlottie-web
over @lottiefiles/dotlottie-react
due to an issue the react package has with config.layout
)
Way to reproduce:
"use client";
import { DotLottieWorker, type Config } from "@lottiefiles/dotlottie-web";
import {
type ComponentPropsWithoutRef,
useEffect,
useLayoutEffect,
useRef,
} from "react";
type DotLottieAnimationProps = ComponentPropsWithoutRef<"canvas"> & {
readonly src: NonNullable<Config["src"]>;
readonly height: string;
readonly width: string;
};
const useIsomorphicLayoutEffect =
typeof window === "undefined" ? useEffect : useLayoutEffect;
function createLottieWorker(canvas: HTMLCanvasElement, src: string): DotLottieWorker {
return new DotLottieWorker({
workerId: "dotlottie-worker",
canvas,
backgroundColor: "transparent",
layout: { fit: "fit-width", align: [0.5, 0.5] },
renderConfig: {
autoResize: true,
freezeOnOffscreen: false,
devicePixelRatio: 5,
},
src,
loop: true,
autoplay: true,
});
}
export function DotLottieAnimation({
src,
height,
width,
style,
...props
}: DotLottieAnimationProps): React.ReactNode {
const ref = useRef<HTMLCanvasElement>(null);
useIsomorphicLayoutEffect(() => {
if (ref.current === null) {
return;
}
const worker = createLottieWorker(ref.current, src);
return () => {
void worker.destroy();
};
}, [ref, src]);
return <canvas ref={ref} style={{ height, width, ...style }} {...props} />;
}
We get the same error just by enabling StrictMode
in our nextjs app.
@flow3d I haven't had time to look into this issue yet, but I'm happy to hear that you accept PRs if someone is interested in helping to fix it
Thanks to @lazybean comment I figured out it happens because createLottieWorker
is called twice when StrictMode
is enabled, causing a side-effect to run twice.
I made this patch to make sure the effect runs only once. This will prevent re-rendering on any state changes, so be aware that this solution might not be suitable for you.
export function DotLottieAnimation({
src,
height,
width,
style,
...props
}: DotLottieAnimationProps): React.ReactNode {
const ref = useRef<HTMLCanvasElement>(null);
useIsomorphicLayoutEffect(() => {
if (ref.current === null) {
return;
}
const { current: canvas } = ref;
// `createLottieWorker` has a side effect, so we have to force a single worker per canvas.
// This is a workaround to prevent multiple workers from being created, which could happen
// when react is on strict mode (development) or when the `src` prop changes.
// It means that changing the props `src` will not cause re-render.
if (canvas.hasAttribute("animation")) {
return;
}
canvas.setAttribute("animation", "true");
const worker = createLottieWorker(canvas, src);
return () => {
void worker.destroy();
};
}, [ref.current, src]);
return <canvas ref={ref} style={{ height, width, ...style }} {...props} />;
}
DotLottieWorkerReact
onNext.js
is throwing the following error: