TW-Elements icon indicating copy to clipboard operation
TW-Elements copied to clipboard

ReferenceError: document is not defined

Open ElbinBinil opened this issue 2 years ago β€’ 12 comments

In next js when I try to import tw-elements the app is getting crashed and giving an message "ReferenceError: document is not defined" image

ElbinBinil avatar Jun 23 '22 08:06 ElbinBinil

Same here, I am assuming it's because of server-side rendering?

EDIT: duplicate of https://github.com/mdbootstrap/Tailwind-Elements/issues/1038 which is still unsolved since January

beeb avatar Jun 23 '22 11:06 beeb

+1

busychild avatar Jun 25 '22 22:06 busychild

What you can do in the meantime is drag the index.min.js (found in /node_modules/tw-elements/dist/js/) into your static folder, then use this inside a custom layout (https://nextjs.org/docs/basic-features/layouts). I personally put it inside a parent div, before the <main>{children}</main>

<Script src="index.min.js"/>

Although, I do not know if this is bad practice or not. The only thing I can think of is that you'll need to update the index.min.js inside your static folder yourself whenever it gets updated upstream.

Taarek avatar Jun 27 '22 08:06 Taarek

@Taarek this way we can have SSR ?

slamer59 avatar Jul 06 '22 21:07 slamer59

This is how I solved it

/_app.tsx

function MyApp({ Component, pageProps }: AppProps) {
  useEffect(() => {
    const use = async () => {
      (await import('tw-elements')).default;
    };
    use();
  }, []);

  return <Component {...pageProps} />;
}

export default MyApp;

Adonis0123 avatar Jul 07 '22 02:07 Adonis0123

@Taarek this way we can have SSR ?

I'm not sure how to see that. I'm pretty new to the whole nextjs/react world.

I haven't ran into any issues at least from what I can tell.

Taarek avatar Jul 07 '22 06:07 Taarek

+1

+1

I'll try what is suggested

uricantasala avatar Jul 26 '22 22:07 uricantasala

This is how I solved it

/_app.tsx

function MyApp({ Component, pageProps }: AppProps) {
  useEffect(() => {
    const use = async () => {
      (await import('tw-elements')).default;
    };
    use();
  }, []);

  return <Component {...pageProps} />;
}

export default MyApp;

It worked like a charm.

Many thanks!

Really appreciated!!

It saved me more time spending on this.

😊 ❀️

uricantasala avatar Jul 26 '22 22:07 uricantasala

This is how I solved it

/_app.tsx

function MyApp({ Component, pageProps }: AppProps) {
  useEffect(() => {
    const use = async () => {
      (await import('tw-elements')).default;
    };
    use();
  }, []);

  return <Component {...pageProps} />;
}

export default MyApp;

Yeah this works. This needs to be in the official documentation somewhere.

locohost avatar Aug 19 '22 16:08 locohost

This is how I solved it

/_app.tsx

function MyApp({ Component, pageProps }: AppProps) {
  useEffect(() => {
    const use = async () => {
      (await import('tw-elements')).default;
    };
    use();
  }, []);

  return <Component {...pageProps} />;
}

export default MyApp;

thanks you so much dude @Adonis0123

devSahinur avatar Sep 01 '22 11:09 devSahinur

Duplicate of #1044 @filipkappa @marveluck Any chance for a fix pretty please? People are have started to resort to some very ridiculous workarounds for this issue.

andrei-ivanov avatar Sep 02 '22 17:09 andrei-ivanov

Hi Guys, for the nextjs users you only need to create the _document.js file with the next <Script/> component

import { Html, Head, Main, NextScript } from 'next/document'
import Script from 'next/script'

// import 'tw-elements';

export default function Document() {
  return (
    <Html>
      <Head />
      <body>
        <Main />
        <NextScript />
        <Script src="./TW-ELEMENTS-PATH/dist/js/index.min.js"/>
      </body>
    </Html>
  )
}

eafelix avatar Sep 08 '22 19:09 eafelix

tried every thing the same problem

bllfoad avatar Oct 21 '22 00:10 bllfoad

finally solved the issue.

I added

  import dynamic from "next/dynamic"
  const {} = dynamic(import("tw-elements"), { ssr: false });

to the index.tsx file which caused another error when deploying the website. I solved that also by adding index.d.ts file to root inside that file, I added

declare module "tw-elements"

line and also added "index.d.ts" to the include in tsconfig.json file

ensarince avatar Jan 05 '23 15:01 ensarince

useEffect(() => { const use = async () => { (await import('tw-elements')).default; }; use(); }, []);

Worked perfectly! Thank you!

svandegar avatar Jan 11 '23 14:01 svandegar

moi j'ai essayΓ© toutes ces methodes mais Γ§a ne marche toujours pas, je fais du nextt js

function MyApp({ Component, pageProps }: AppProps) { ~~useEffect~~ (() => { const use = async () => { (await import('~~tw-elements~~')).default; }; use(); }, []);

return <Component {...pageProps} />; }

export default MyApp;

le code est soulignΓ©

juvenalBOBENZE avatar Mar 03 '23 17:03 juvenalBOBENZE

Please, about this issue, i can not get my component to see the script js file, so it's not working properly any tw-elements component I am trying to use. I did: in tailwind.config.js content: [ "./pages//*.{js,ts,jsx,tsx}", "./components//.{js,ts,jsx,tsx}", "./src/**/.{html,js}", "./node_modules/tw-elements/dist/js/**/*.js", "./node_modules/react-tailwindcss-datepicker/dist/index.esm.js", ], plugins: [require("tw-elements/dist/plugin"), require("@tailwindcss/forms")],

////

in _app.js i did:

useEffect(() => { const use = async () => { ;(await import("tw-elements")).default } use() }, [])

//// and finally i try to use some of the codein tw-elemts but they are not working

what am i doing wrong?

izzie91 avatar Mar 05 '23 02:03 izzie91

Tried everthing above, still no success, considering i'm using Next 13. Pls if someone find a better solution pls help.

VictorSS avatar Mar 05 '23 18:03 VictorSS

Hi, we just have launched bunch of integration tutorials - both with CSR and SSR frameworks. If you have more questions about integration or you still got some problems with particular components, let us know by adding new issue / topic in discussions section (if there are some unclrear informations or just want let us know about something).

Next.js integration tutorial.

Trochonovitz avatar Mar 24 '23 10:03 Trochonovitz

@Trochonovitz link is broken btw

stevebrowndotco avatar Mar 26 '23 13:03 stevebrowndotco

Hey, guys! This is my approach with a NextJS 13 and new AppRouter.

  1. Create component for the initialisation of TWElements
"use client";
import { useEffect } from 'react';

export const TWElementsInit = () => {
  useEffect(() => {
    ;(async () => (await import('tw-elements')))()
  }, []);
  return null
}
  1. Import into app/layout.tsx (which replaced the old one '_app.tsx')
import './globals.css'
import {TWElementsInit} from './tw'

export const metadata = {
  title: 'Title,
  description: 'description,
}

export default function RootLayout({
  children,
}: {   children: React.ReactNode
  }) {
  return (
    <html lang="en">
      <TWElementsInit/>
      <body>{children}</body>
    </html>
  )
}

Good luck! :)

rain84 avatar Apr 16 '23 12:04 rain84

Hi, we just have launched bunch of integration tutorials - both with CSR and SSR frameworks. If you have more questions about integration or you still got some problems with particular components, let us know by adding new issue / topic in discussions section (if there are some unclrear informations or just want let us know about something).

Next.js integration tutorial.

@Trochonovitz The tutorial steps do not work. The components load but do not function. Also using import with dynamic gave a type error.

  Type '() => Promise<typeof import("/.../pages/component.ts")>' is not assignable to type '() => LoaderComponent<{}>'.
    Type 'Promise<typeof import("/.../pages/component.ts")>' is not assignable to type 'LoaderComponent<{}>'.
      Type 'typeof import("/.../pages/component.ts")' is not assignable to type 'ComponentType<{}> | ComponentModule<{}>'.ts(2345)
      ```

vforvasquez avatar Apr 19 '23 23:04 vforvasquez

@vforvasquez change your file extension to .tsx instead of .ts.

Trochonovitz avatar Apr 21 '23 10:04 Trochonovitz

Hey, guys! This is my approach with a NextJS 13 and new AppRouter.

  1. Create component for the initialisation of TWElements
"use client";
import { useEffect } from 'react';

export const TWElementsInit = () => {
  useEffect(() => {
    ;(async () => (await import('tw-elements')))()
  }, []);
  return null
}
  1. Import into app/layout.tsx (which replaced the old one '_app.tsx')
import './globals.css'
import {TWElementsInit} from './tw'

export const metadata = {
  title: 'Title,
  description: 'description,
}

export default function RootLayout({
  children,
}: {   children: React.ReactNode
  }) {
  return (
    <html lang="en">
      <TWElementsInit/>
      <body>{children}</body>
    </html>
  )
}

Good luck! :)

and how do you init Carousel for example?

carlosriveroib avatar May 24 '23 07:05 carlosriveroib

Hey, guys! This is my approach with a NextJS 13 and new AppRouter.

  1. Create component for the initialisation of TWElements
"use client";
import { useEffect } from 'react';

export const TWElementsInit = () => {
  useEffect(() => {
    ;(async () => (await import('tw-elements')))()
  }, []);
  return null
}
  1. Import into app/layout.tsx (which replaced the old one '_app.tsx')
import './globals.css'
import {TWElementsInit} from './tw'

export const metadata = {
  title: 'Title,
  description: 'description,
}

export default function RootLayout({
  children,
}: {   children: React.ReactNode
  }) {
  return (
    <html lang="en">
      <TWElementsInit/>
      <body>{children}</body>
    </html>
  )
}

Good luck! :)

and how do you init Carousel for example?

Like so

export const TWElementsInit = () => {
  useEffect(() => {
    (async () => {
      const { initTE, Carousel } = await import('tw-elements');
      initTE({ Carousel });
    })();
  }, []);
  return null;
};

Tried everything and nothing worked except for adding this code for every component I'm creating:

"use client";
import { useEffect } from "react";
const AppSelect = () => {
    useEffect(() => {
        const init = async () => {
            const { Select, initTE } = await import("tw-elements");
            initTE({ Select });
        };
        init();
    }, []);
    return (
        <>
            <select data-te-select-init multiple>
                <option value="1">One</option>
                <option value="2">Two</option>
                <option value="3">Three</option>
                <option value="4">Four</option>
                <option value="5">Five</option>
                <option value="6">Six</option>
                <option value="7">Seven</option>
                <option value="8">Eight</option>
            </select>
            <label data-te-select-label-ref>Example label</label>

        </>
    );
};

export default AppSelect;

AliAbdllah avatar Jul 29 '23 10:07 AliAbdllah

Does anyone have a solution to this using SvelteKit??

ignitehub-dev avatar Oct 06 '23 20:10 ignitehub-dev

@ignitehub-dev I've just run into this issue today in my SvelteKit project. Kudos to the guys above, a SvelteKit alternative to their NextJS code seems to work:

<script context="module">
  import { onMount } from 'svelte'; // import onMount either here or in the next script
  export function initTWE() {
    onMount(async () => {
      const { initTE, Select } = await import('tw-elements');
      initTE({ Select });
    });
  }
</script>

and then

<script>
initTWE()
</script>

Not sure if it's stable but at least it stopped raising VITE SSR error.

Disclaimer: I'm not even a dev, just a PM learning some JS with Svelte :)

IliaNikonorov avatar Oct 16 '23 17:10 IliaNikonorov

@IliaNikonorov i gave up on using TW-Elements as a js package. I found it not to interact nicely when trying to link actions between components with svelteKit. I migrated my project to use Skeleton.

ignitehub-dev avatar Oct 16 '23 20:10 ignitehub-dev