Explain Codes LogoExplain Codes Logo

Window is not defined in Next.js React app

javascript
window-access
next-js
ssr
Alex KataevbyAlex Kataev·Mar 14, 2025
TLDR
// useEffect to the rescue! import { useEffect } from 'react'; const SafeWindow = () => { useEffect(() => { // Window walks into a bar here... (sorry, bad joke) console.log(window.location.href); }, []); // Hangs out just once right after mounting return <div>Window-Safe is my middle name</div>; }; export default SafeWindow;

window, meet useEffect. Remember, only in useEffect, to prevent awkward window not defined moments in your Next.js SSR journey.

How to avoid window pains in SSR

In the Next.js world, the sun shines (code runs) on both server and client land. window can be found sunbathing in the browser, but in the server... well, no windows there—thus, the infamous "Window is not defined" error.

Using dynamic import for client folks only

For modules that do hangouts only in browser land (client) - dynamic import them. This way, they won't sneak into server-side rendering (SSR) and create scenes.

import dynamic from 'next/dynamic'; const ClientSideComponent = dynamic( () => import('./ClientOnlyComponent'), // import as promise like a boss { ssr: false } // SSR need not apply );

Custom hooks for window resizing

Does your component need to keep an eye on the window size? Create a custom hook for that!

function useWindowSize() { // Window, are you home? const isClient = typeof window === 'object'; function getSize() { // Window dimensions or nada return { width: isClient ? window.innerWidth : undefined, height: isClient ? window.innerHeight : undefined, }; } const [windowSize, setWindowSize] = useState(getSize); useEffect(() => { if (!isClient) { return false; // no one's home :( } function handleResize() { setWindowSize(getSize()); } // Handle the event like you're born for this! window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); // Cleaning up after party }, []); // Empty array ensures party (effect) is only thrown once return windowSize; }

Lifecycles and Hooks: The Rescue Squad

componentWillMount has left the building. The new sheriff is either useEffect or componentDidMount. Remember, they're the gatekeepers to accessing window.

Using componentDidMount for window access

When using class components, the componentDidMount lifecycle method is the bouncer - "You shall not pass until I'm done!", keeping window safe.

class SafeWindowComponent extends React.Component { componentDidMount() { // The safe and sound zone for window console.log(window.innerHeight); // Here's my badge, Window! } render() { return <div>Class Component, window-duty done right!</div>; } }

Functional components with useEffect to the rescue

For functional components, useEffect is the hero, similar to componentDidMount, componentDidUpdate, and componentWillUnmount bunched into one.

import { useState, useEffect } from 'react'; const SafeWindowFunctional = () => { const [innerHeight, setInnerHeight] = useState(0); useEffect(() => { setInnerHeight(window.innerHeight); // Safe and sound here! // The caretaker that cleans-up: return () => { // Cleaning-up duties go here }; }, []); // Empty array indicates its a one-time gig return <div>The inner height is {innerHeight}px</div>; };

Universal libraries and Component Redesign

The code needs to run on both browser and server land. So when it comes to handling window, universal or isomorphic libraries get the job done! They work both sides, server and client.

Component care with window in server-side rendering

Take some time to redesign components so they understand what server-side rendering means and safely handle window.

const MyComponent = () => { const isBrowser = typeof window !== 'undefined'; if (isBrowser) { // Enjoy your window view here! } return ( // Some cool JSX ); };

The Next.js code Garden

Growing a beautiful Next.js code garden demands structured planting, nourishment, and regular prunes.

Planting client-side code wisely

Plant (keep) client-side code in its own plot (section). It's like having a herb garden in a backyard - efficient and easy to maintain.

Regular clean-up saves you pain

Listened to events like resize or scroll on window? When the season changes (component unmounts), make sure the plot (memory) is clean and ready for next season(component).

Conditional rendering is your friend

Use conditional rendering to ensure right plants (components) are grown in a suitable climate (environment). This helps to avoid unexpected frosts (React hydration errors).