Saltar al contenido principal
Next.js

Solución: localStorage is not defined en Next.js y SSR

localStorage no existe en el servidor — solo en el navegador. Error típico en Next.js, Astro y cualquier framework con SSR. Todas las soluciones para acceder a APIs del browser de forma segura.

Error: ReferenceError: localStorage is not defined

¿Por qué ocurre?

Durante el Server-Side Rendering (SSR), el código se ejecuta en Node.js — un entorno sin navegador. localStorage, window, document y navigator no existen en Node.js. Si los usas directamente en el cuerpo del componente o en el servidor, Next.js lanza ReferenceError.

Solución paso a paso

Solución A — Comprueba typeof window antes de acceder:

// ✅ Guarda para cualquier uso de APIs del navegador
const esBrowser = typeof window !== 'undefined';

if (esBrowser) { const valor = localStorage.getItem('tema'); }

Solución B — Solo en useEffect (client-side):

import { useEffect, useState } from 'react';

function Componente() { const [tema, setTema] = useState('claro'); // valor inicial seguro

useEffect(() => { // useEffect solo se ejecuta en el cliente, nunca en el servidor const temaGuardado = localStorage.getItem('tema') ?? 'claro'; setTema(temaGuardado); }, []);

return

...
; }

Solución C — Dynamic import con ssr: false (Next.js):

// Para componentes enteros que dependen de APIs del browser
import dynamic from 'next/dynamic';

const ComponenteBrowser = dynamic( () => import('../components/UsaLocalStorage'), { ssr: false } // no renderizar en el servidor );

Solución D — Hook personalizado seguro:

// hooks/useLocalStorage.ts
import { useState, useEffect } from 'react';

export function useLocalStorage(clave: string, valorInicial: T) { const [valor, setValor] = useState(valorInicial);

useEffect(() => { try { const item = localStorage.getItem(clave); if (item !== null) setValor(JSON.parse(item)); } catch { // localStorage puede estar bloqueado (modo privado, etc.) } }, [clave]);

const guardar = (nuevoValor: T) => { try { setValor(nuevoValor); localStorage.setItem(clave, JSON.stringify(nuevoValor)); } catch {} };

return [valor, guardar] as const; }

// Uso const [tema, setTema] = useLocalStorage('tema', 'claro');

Lo mismo aplica para window, document, navigator:

// ❌ Falla en SSR
const ancho = window.innerWidth;

// ✅ Dentro de useEffect o con comprobación useEffect(() => { const ancho = window.innerWidth; }, []);

Cómo evitarlo en el futuro

En Next.js o cualquier framework SSR, trata localStorage y window como APIs asíncronas que solo existen después del mount. Usa siempre useEffect o comprueba `typeof window !== 'undefined'` antes de acceder.

Next.jsSSRReactErrorbrowser

¿Quieres que una IA te ayude? Genera el prompt perfecto para tu error:

Generador de Prompts

¿Necesitas desarrollo a medida?

Apps web, IA, módulos ERP — cuéntame tu proyecto.