Matthew C.
—In Next.js version 13+, you may have encountered the following error when trying to use the localStorage
browser API if you used the window.localStorage
property:
Error: window is not defined
You may have encountered the following error if using the localStorage
property:
Error: localStorage is not defined
In a browser environment, windows.localStorage
is the same as localStorage
, and localStorage
is a property of the global window
object.
This error occurs because, from Next.js version 13, components are server-rendered by default. Components are pre-rendered into HTML on the server before being sent to the client. The window
object is not available on the server.
We need to make sure that the code to get values from local storage and save values to local storage only runs on the client where the window
object is defined. We can do this by using the useEffect
hook in a Next.js client component or by lazy loading the component.
To use browser APIs like the window
object, create a client component by adding the React "use client"
directive at the top of your component file, above your imports. Client components are pre-rendered on the server, like server components, for a fast initial payload.
The client component is then made interactive by adding event listeners to the static HTML. This process is called hydration. Client components render on the server and the client.
useEffect
in a Client ComponentTo make sure that the code using the window
object is run on the client only, add it to a useEffect
hook.
Below is an example counter component that stores a count state variable in local storage:
"use client"; import { useState, useEffect } from "react"; export default function Counter() { const [count, setCount] = useState(null); useEffect(() => { const savedValue = window.localStorage.getItem("count"); setCount(savedValue ? Number(savedValue) : 0); }, []); useEffect(() => { if (typeof count === "number") { window.localStorage.setItem("count", count); } }, [count]); return ( <button onClick={() => setCount(count + 1)}> Count: {typeof count === "number" ? count : <span>...</span>} </button> ); }
In this component, a button is rendered that increments the count
state variable by 1 when it’s clicked. The first useEffect
hook gets the value for count
from local storage or sets it to 0 if it has not been added to local storage yet. The second useEffect
saves the value of the count
variable to state when the useEffect’s dependency, count
, changes. This happens when the button is clicked.
Alternatively, you can lazy load your client component and disable pre-rendering on the server so that it’s only rendered on the client. This may increase the time taken for the page to initially load. This approach is useful when using a client-only library or when you want to defer loading the component until a specific action happens, such as the user clicking a button.
Tasty treats for web developers brought to you by Sentry. Get tips and tricks from Wes Bos and Scott Tolinski.
SEE EPISODESConsidered “not bad” by 4 million developers and more than 100,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.
Here’s a quick look at how Sentry handles your personal information (PII).
×We collect PII about people browsing our website, users of the Sentry service, prospective customers, and people who otherwise interact with us.
What if my PII is included in data sent to Sentry by a Sentry customer (e.g., someone using Sentry to monitor their app)? In this case you have to contact the Sentry customer (e.g., the maker of the app). We do not control the data that is sent to us through the Sentry service for the purposes of application monitoring.
Am I included?We may disclose your PII to the following type of recipients:
You may have the following rights related to your PII:
If you have any questions or concerns about your privacy at Sentry, please email us at compliance@sentry.io.
If you are a California resident, see our Supplemental notice.