Catching the "window is not defined" error
Answered
Silver carp posted this in #help-forum
Silver carpOP
Hi!
I'm using Telegram's SDK for my webapp and in it's internal it's trying to access
I've tried putting
Everything is run on local machine with
I thought maybe I'll just catch this error and deal with it but I still get the error anytime I refresh the page.
So my question is, what is the correct way of handling such issue?
I'm using Telegram's SDK for my webapp and in it's internal it's trying to access
window object, which may be not initialized, so it throws an error ReferenceError: window is not defined.I've tried putting
'use client' and 'client only' in affected files, but doesn't seem to change anything.Everything is run on local machine with
npm run dev (next dev).I thought maybe I'll just catch this error and deal with it but I still get the error anytime I refresh the page.
So my question is, what is the correct way of handling such issue?
// ./app/page.tsx
'use client'
import { Suspense, useEffect } from "react";
import Main from "@/components/sections/main";
import TWA from "../lib/telegram";
export default function Home() {
useEffect(() => TWA?.ready);
return (
<Main>
<Suspense fallback={<p>Loading...</p>}>
<h1 className="text-3xl font-bold underline">Hello world!</h1>
</Suspense>
</Main>
);
};// ./lib/telegram
'use client'
import WebApp from "@twa-dev/sdk";
const windowNotDefinedCatcher = (fn: Function) => {
try {
return fn()
} catch (error) {
console.log("Error: " + error)
if (error instanceof Error) {
if (error.message.includes("window is not defined")) {
console.warn("Telegram WebApp: window is not defined!")
} else {
console.error(error)
// throw error
}
}
}
}
const version = () => windowNotDefinedCatcher(() => WebApp.version)
const ready = () => {
windowNotDefinedCatcher(() => {
WebApp.ready();
console.debug("WebApp version: " + version());
})
}
const TWA = (() => {
return {
version: version,
ready: ready,
}
})();
export default TWA;Answered by Asian paper wasp
You could do something like this:
useEffect(() => {
// this will run on client-side only
import("@twa-dev/sdk") // dynamic import
.then(WebApp => {
// do your stuff
})
}, [])9 Replies
Silver carpOP
// log
debian@DESKTOP-****:~/dev/<project_id>$ npm run dev
> <project_id>@0.0.1 dev
> next dev
â–² Next.js 14.1.3
- Local: http://localhost:3000
- Environments: .env.local
✓ Ready in 1286ms
â—‹ Compiling / ...
✓ Compiled / in 2.5s (3605 modules)
⨯ node_modules/@twa-dev/sdk/dist/telegram-web-apps.js (248:0) @ eval
⨯ ReferenceError: window is not defined
at __webpack_require__ (/home/debian/dev/<project_id>/.next/server/webpack-runtime.js:33:42)
at __webpack_require__ (/home/debian/dev/<project_id>/.next/server/webpack-runtime.js:33:42)
at __webpack_require__ (/home/debian/dev/<project_id>/.next/server/webpack-runtime.js:33:42)
at eval (./lib/telegram.tsx:5:70)
at (ssr)/./lib/telegram.tsx (/home/debian/dev/<project_id>/.next/server/app/page.js:403:1)
at __webpack_require__ (/home/debian/dev/<project_id>/.next/server/webpack-runtime.js:33:42)
at eval (./app/page.tsx:12:71)
at (ssr)/./app/page.tsx (/home/debian/dev/<project_id>/.next/server/app/page.js:286:1)
at __webpack_require__ (/home/debian/dev/<project_id>/.next/server/webpack-runtime.js:33:42)
at JSON.parse (<anonymous>)
null
✓ Compiled in 413ms (1669 modules)Asian paper wasp
Catch the error will not help.
First of all, understand the issue. The library is trying to access window without any checking. This means it can ONLY be used on the client side. You need some logics to handle that. There are many examples online.
use client just make the components go through hydration. It will still attempt to be SSRed.
client only is merely a safe guard that complains if the file is not only running on the client side. It have no logic of forcing it runs on client side only
First of all, understand the issue. The library is trying to access window without any checking. This means it can ONLY be used on the client side. You need some logics to handle that. There are many examples online.
use client just make the components go through hydration. It will still attempt to be SSRed.
client only is merely a safe guard that complains if the file is not only running on the client side. It have no logic of forcing it runs on client side only
Silver carpOP
I've tried searching similar issue and I couldn't find anything that would work. That's why I'm asking here.
What else do I need to do to ensure that code only runs on client side? Why is
This doesn't work https://github.com/vercel/next.js/issues/2473#issuecomment-362119102
What else do I need to do to ensure that code only runs on client side? Why is
useEffect not enough?This doesn't work https://github.com/vercel/next.js/issues/2473#issuecomment-362119102
Asian paper wasp
Why is useEffect not enough?This needs to bring us to the source code the package.
If you take a look at https://github.com/twa-dev/SDK/blob/master/src/sdk.ts (
sdk.ts is imported in index.ts), you will notice window is immediately being used. That means, the moment you do import WebApp from "@twa-dev/sdk";, the application is already trying to access windowAsian paper wasp
You could do something like this:
useEffect(() => {
// this will run on client-side only
import("@twa-dev/sdk") // dynamic import
.then(WebApp => {
// do your stuff
})
}, [])Answer
Silver carpOP
Thanks man, I will try
Silver carpOP
@Asian paper wasp Yeah, dynamic import woks for me. Thanks again!
@Silver carp <@416197049143525376> Yeah, dynamic import woks for me. Thanks again!
Mark his ans as the solution :D
Silver carpOP
const { default: WebApp } = await import("@twa-dev/sdk") // dynamic import