When working with React and Next.js, you may encounter the “window is not defined” error. This error occurs when trying to access the window
object, which represents the browser environment, in a context where it is not available, such as during server-side rendering (SSR) or in Node.js.
In this article, we’ll explore different approaches to solving this error and ensure that your client-side code executes correctly.
Why the Error Occurs
Next.js is a React framework with pre-rendering capabilities. It generates the HTML of each page on the server for better SEO and performance. However, the window
object is only available in the browser environment and not in the Node.js runtime.
If you try to access window
directly, like this:
// components/Scroll.js
window.addEventListener("scroll", function() {
console.log("scroll!");
});
You will encounter the “ReferenceError: window is not defined” error.
Solution 1: Using typeof
One way to solve this error is by using the typeof
operator to check if window
is defined before accessing it.
if (typeof window !== "undefined") {
// Browser code
}
The typeof
operator returns the type of the operand as a string. If window
is not defined, typeof window
will evaluate to "undefined"
without throwing an error.
Solution 2: Using the useEffect
Hook
Another approach is to use the useEffect
React hook. The useEffect
hook runs only during the rendering phase, so it won’t execute on the server.
Here’s an example of using useEffect
to safely access window
:
// components/Scroll.js
import React, { useEffect } from "react";
export default function Scroll() {
useEffect(function mount() {
function onScroll() {
console.log("scroll!");
}
window.addEventListener("scroll", onScroll);
return function unMount() {
window.removeEventListener("scroll", onScroll);
};
});
return null;
}
In this example, the useEffect
hook is used to register the scroll event listener when the component mounts and remove it when the component unmounts.
Solution 3: Dynamic Imports
If you’re importing external modules that depend on window
, you can use dynamic imports with the ssr: false
option. This way, the component won’t be rendered on the server-side at all.
// pages/index.js
import dynamic from "next/dynamic";
const Scroll = dynamic(
() => {
return import("../components/Scroll");
},
{ ssr: false }
);
export default function Home() {
return (
<div style={{ minHeight: "1000px" }}>
<h1>Home</h1>
<Scroll />
</div>
);
}
By dynamically importing the Scroll
component and setting ssr: false
, you ensure that it is only loaded and rendered on the client-side.
Conclusion
The “window is not defined” error is a common issue when working with React and Next.js. By using techniques like conditional checks with typeof
, the useEffect
hook, or dynamic imports, you can handle this error and ensure that your client-side code executes correctly.
Remember to consider the specific requirements of your application and choose the approach that best fits your needs.