#Catching the "window is not defined" error

12 messages · Page 1 of 1 (latest)

exotic shore
#

Hi!
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;
lone meadowBOT
#

🔎 This post has been indexed in our web forum and will be seen by search engines so other users can find it outside Discord

🕵️ Your user profile is private by default and won't be visible to users outside Discord, if you want to be visible in the web forum you can add the "Public Profile" role in id:customize

✅ You can mark a message as the answer for your post with Right click -> Apps -> Mark Solution
(if you don't see the option, try refreshing Discord with Ctrl + R)

exotic shore
#
// 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)
icy totem
#

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

exotic shore
#

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 useEffect not enough?
This doesn't work https://github.com/vercel/next.js/issues/2473#issuecomment-362119102

GitHub

I have a callback route in my application that receives access token from auth process in URL hash fragment. I'd like to parse it and save into redux store. I used to get it through window.loca...

icy totem
#

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 window

GitHub

npm package for TWA SDK. Contribute to twa-dev/SDK development by creating an account on GitHub.

#

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
    })
}, [])
exotic shore
#

Thanks man, I will try

exotic shore
#

@icy totem Yeah, dynamic import woks for me. Thanks again!

bleak hemlock
exotic shore
#
const { default: WebApp } = await import("@twa-dev/sdk") // dynamic import
lone meadowBOT
#
✅ Success!

This question has been marked as answered! If you have any other questions, feel free to create another post

Jump to answer

[Click here](#1217479121077276722 message)