lottie-react
lottie-react copied to clipboard
ReferenceError: document is not defined at createTag...
Hello everyone,
I had some issues with ReferenceError (with SSR). And yes I know, it could be solved by dynamic import, lazy or maybe some other ways.
But the situation is like below:
- There is a main(index) page with Lottie (lottie-react)
- I've even use useEffect with isMount state to render the Lottie after the mount
case1.
- No errors and works fine in Node 18 (v.18.18.0)
case2.
- ReferenceError: document is not defined at createTag... occurs in higher version of Node (20, 21)
So, we (I and my co-worker) decided to fix Node version to 18 and it works fine.
But we are just curious about it. Try to figure it out but all we can find is that the node version effects build in somehow.
If anyone knows what has been changed between 18 and higher, it would be nice to know of it.
Thank you so much.
Got the same error
Got the same error, but everything works fine
Same error.
use nvm 18.18.2 for temporary
same error with node 21
Hey folks, this error happens because lottie-web, dependency of lottie-react depends on the condition of typeof navigator !== "undefined" to determine if it runs in browser or server environment:
if (typeof navigator !== "undefined") {
// client-side code
} else {
// server-side code
}
This is not valid anymore though, because Node v21 introduces a new navigator API, previously present only in client-side code. So document is now reached when being run in Node. One solution would be for lottie-web to just change that condition to one that clearly distinguishes between client and server.
Hey folks, this error happens because
lottie-web, dependency oflottie-reactdepends on the condition oftypeof navigator !== "undefined"to determine if it runs in browser or server environment:if (typeof navigator !== "undefined") { // client-side code } else { // server-side code }This is not valid anymore though, because Node v21 introduces a new navigator API, previously present only in client-side code. So
documentis now reached when being run in Node. One solution would be forlottie-webto just change that condition to one that clearly distinguishes between client and server.
Thank you so much! I was so wondering why this happenend and thanks for the sharing.^_^
@ZhariffAdam
Why was this issue closed? Was solved? Is there a plan for support for node 21?
Thank you for now
this issue should remain open. not fixed for node >= 20
this issue should remain open. not fixed for node >= 20
+1
Oh I am sorry. I didn't know it has to be open until the fix. I will reopen it~
thanks @Beruguru 🙏 i worked on a workaround with some additional benefits Lazyloading the lottie module as loading lazily the animation json
- less bundle from package - which is pretty large (81.9 kB MINIFIED + GZIPPED) - https://bundlephobia.com/package/[email protected]
- less bundle for loading the json - will be load lazily as well - as they can get quite large as well
EDIT: I had a chance to write a small article
https://medium.com/@alonmiz1234/lazy-load-lottie-animation-in-react-e58e67e2aa74
this example uses Skeleton from mantine but it can be replace with a simple loading animation you already have
LazyLottie (Optimized for SSR)
import { Skeleton } from '@mantine/core';
import { useQuery } from '@tanstack/react-query';
import { type LottieComponentProps } from 'lottie-react';
import { Suspense, lazy, useEffect, useRef, useState } from 'react';
const LazyLottieComponent = lazy(() => import('lottie-react'));
interface LottieProps<T extends Record<string, unknown>> {
getJson: () => Promise<T>;
id: string;
}
export function LazyLottie<T extends Record<string, unknown>>({
getJson,
id,
ref,
...props
}: LottieProps<T> & Omit<LottieComponentProps, 'animationData'>) {
const { data } = useQuery({
queryKey: [id],
queryFn: getJson,
enabled: typeof window !== 'undefined',
});
if (!data) return <Skeleton height={props.height} width={props.width} />;
return (
<Suspense fallback={<Skeleton height={props.height} width={props.width} />}>
<LazyLottieComponent animationData={data} {...props} />
</Suspense>
);
}
Usage
export const EmptyState: React.FC = () => {
return (
<LazyLottie
getJson={() => import('../../../assets/lottie/empty-box.json')}
loop
id="empty-box"
width={120}
height={120}
/>
);
};
Next.js. Lottie-web uses the window object, which is not available during SSR. To fix this use the following code: Ref here
import dynamic from 'next/dynamic';
const Lottie = dynamic(() => import('react-lottie'), { ssr: false });
Running into this issue consistently from using lottie-react in a component library that doesn't use next with nodejs 20.12.2. Lazy importing react-lottie or the component itself doesn't work either.
@alan-nousot If you're importing a named export that uses lottie-react, you can try the following:
const Component = dynamic(
async () =>
import('library').then(({ Component }) => ({
default: Component, // note the alias to `default`!
})),
{ ssr: false },
);
Use node 18.17.0 to resolve