Table of Contents
If you are working with Next.js and accessing the window
object for the first time, there are high chances that you have seen the below error:
ReferenceError: window is not defined
In this article, we will see why this error occurs and different ways to fix the error.
Project setup
First, let's create a Next.js application using the following command:
1npx create-next-app next-window-not-defined
Reproducing the error
Once the project is setup, update the index.js
with the following code:
1import styles from "../styles/Home.module.css"23export default function Home() {4 window.welcomeMessage = "Welcome to CodingDeft!"5 return <div className={styles.container}>Hello</div>6}
Here inside the Home
component, we are setting a value to window.welcomeMessage
.
In JavaScript applications or normal react applications, this should work fine.
But if we run the code and see we will see the following error:
Also, if you check the terminal where you have started the application, you will see the error there as well:
The root cause of the error
As you can see the error occurs in the terminal itself. That means it is a compilation error.
Next.js is compiled/built on Node.js runtime and Node.js does not have the the window
object.
Now you may ask, why it should run on Node.js? This is because, Next.js is server-side rendered, and it runs the component code in the server, sends the HTML to the browser, and the HTML gets hydrated in the browser.
Different ways of fixing the error
In this section, we will explore different ways how to fix the error
Checking if the window is defined
The very obvious fix would be to check if the window
object exists or not, and access the window only if it exists.
1import styles from "../styles/Home.module.css"23export default function Home() {4 if (typeof window !== "undefined") {5 window.welcomeMessage = "Welcome to CodingDeft!"6 }7 return <div className={styles.container}>Hello</div>8}
Now if you run the code, you will not see the error.
Accessing the window inside useEffect
The useEffect hook does not run in the server side.
So we can have the code which needs to run only on the client-side inside a useEffect
hook.
1import styles from "../styles/Home.module.css"23export default function Home() {4 useEffect(() => {5 window.welcomeMessage = "Welcome to CodingDeft!"6 }, [])78 return <div className={styles.container}>Hello</div>9}
Dynamic imports in Next.js
Say you are accessing the window object in multiple places within your component, and it would not be feasible to use the above methods all the time.
In cases where you want the whole component to be run only on the client side, you can use the dynamic import feature of Next.js
First, let's create folder named components
in the root of the project and a component named ClientComponent
inside it:
1import React from "react"23const ClientComponent = () => {4 window.welcomeMessage = "Welcome to CodingDeft!"56 return <div>Hello</div>7}89export default ClientComponent
Now we can import the ClientComponent
dynamically as shown below:
1import styles from "../styles/Home.module.css"23import dynamic from "next/dynamic"45const ClientComponent = dynamic(() => import("../components/ClientComponent"), {6 // Do not import in server side7 ssr: false,8})910export default function Home() {11 return (12 <div className={styles.container}>13 <ClientComponent />14 </div>15 )16}
Now if you run the code, you will not see the error.
Do follow me on twitter where I post developer insights more often!