Fixing 'localStorage is not defined' Error in Next.js

Fixing 'localStorage is not defined' Error in Next.js

One of the common errors developers encounter in Next.js is the dreaded localStorage is not defined error. This issue arises because localStorage is a part of the browser's window object, which is not available during server-side rendering. In this article, we'll explore why this error occurs and how to fix it.

Why Does This Error Occur?

In Next.js, components are server-rendered by default. This means that your JavaScript code runs on the server before it gets sent to the client. Since localStorage is a browser-specific API, trying to access it on the server side will throw an error.

Solutions to Fix the Error

Using useEffect Hook

One of the simplest ways to resolve this error is by using the useEffect hook. This hook runs only on the client side, after the initial render.

import { useEffect } from 'react';
 
const MyComponent = () => {
  useEffect(() => {
    const storedValue = localStorage.getItem('myKey');
    console.log(storedValue);
  }, []);
 
  return <div>Check the console for localStorage value</div>;
};
 
export default MyComponent;

By placing the localStorage access inside useEffect, you ensure it runs only in the browser environment.

Conditional Checks

Another approach is to check if the window object is defined before accessing localStorage.

const MyComponent = () => {
let storedValue;
if (typeof window !== 'undefined') {
storedValue = localStorage.getItem('myKey');
}
 
return <div>{storedValue}</div>;
};
 
export default MyComponent;

This method prevents the code from executing on the server side.

Dynamic Import with ssr: false

For components that rely heavily on browser APIs, you can dynamically import them and disable server-side rendering.

import dynamic from 'next/dynamic';
 
const BrowserComponent = dynamic(() => import('../components/BrowserComponent'), {
ssr: false,
});
 
const MyPage = () => (
  <div>
    <h1>Hello Next.js</h1>
    <BrowserComponent />
  </div>
);
 
export default MyPage;

Setting ssr: false ensures that the component is only rendered on the client side.

Practical Example

Let's combine these techniques into a practical example. Suppose we have a component that reads from localStorage and displays the stored value.

import { useEffect, useState } from 'react';
import dynamic from 'next/dynamic';
 
const BrowserComponent = () => {
const [value, setValue] = useState('');
 
useEffect(() => {
const storedValue = localStorage.getItem('myKey');
setValue(storedValue || '');
}, []);
 
return <div>Stored Value: {value}</div>;
};
 
const MyPage = () => (
<div>
    <h1>Hello Next.js</h1>
    <dynamic(() => import('../components/BrowserComponent'), { ssr: false }) />
</div>
);
 
export default MyPage;`

Conclusion

Handling the localStorage is not defined error in Next.js involves understanding the distinction between server-side and client-side rendering. By using hooks like useEffect, conditional checks, and dynamic imports, you can effectively manage browser-specific code. For more detailed information, you can refer to the Next.js documentation and related articles.

Additional Resources

Thanks for Reading!

If you enjoyed this article and found it useful, and you'd like to explore more on coding, feel free to support me by buying me a coffee ☕️ or by following me on Instagram @bilalelmahdaoui and X (formerly Twitter) @bilalelmahdaoui. I regularly post updates, insights, videos, and podcasts, all focused on the latest in Angular. Stay tuned and don’t miss out on what’s happening! ✨