En el constructor de reactjs y nextjs obteniendo un error de referencia: el almacenamiento local no está definido

4 minutos de lectura

avatar de usuario
Toni Suwendi

Hago el sistema jsonwebtoken en reactjs y uso nextjs. encuentro un problema cuando ejecuto el código en el navegador que es localStorage no está definido.

este es mi código en el archivo AuthStudentContext.js

import React from 'react'
import axios from 'axios'

const axiosReq = axios.create()
const AuthStudentContext = React.createContext()

export class AuthStudentContextProvider extends React.Component {

    constructor() {
        super()
        this.state = {
            students: [],
            student: localStorage.getItem('student') || {},
            token: localStorage.getItem('token') || "",
            isLoggedIn: (localStorage.getItem('student' == null)) ? false : true
        }
    }

    login = (credentials) => {
        return axiosReq.post("http://localhost:4000/api/login", credentials)
            .then(response => {
                const { token } = response.data
                localStorage.setItem("token", token)

                this.setState({
                    token,
                    isLoggedIn: true
                })

                return console.log(response)
            })
    }

y mostrar error localStorage no está definido

  • usar ventana.almacenamiento local

    – avck

    31 de diciembre de 2019 a las 6:28

  • y luego la ventana no está definida

    – Toni Suwendi

    31 de diciembre de 2019 a las 6:30

  • ¿Puedes publicar el fragmento con error? la ventana debe estar disponible en el espacio de nombres global

    – avck

    31 de diciembre de 2019 a las 6:31

  • Lo siguiente es anular el objeto de la ventana en todas partes, excepto que el componente se montó. : stackoverflow.com/a/55151122/1643143

    – avck

    31 de diciembre de 2019 a las 6:34

  • votando para reabrir esto ya que la pregunta fue editada con más detalles.

    – fuijun

    21 de junio de 2020 a las 10:44

Como todos ya mencionaron, NextJS se ejecuta tanto en el cliente como en el servidor. En el servidor, no hay localStoragepor lo tanto, la undefined error.

Sin embargo, una solución alternativa es verificar si nextjs se está ejecutando en el servidor antes de acceder al localStorage. es decir

const ISSERVER = typeof window === "undefined";

if(!ISSERVER) {
 // Access localStorage
 ...localStorage.get...
}

Sobre el constructor así como componentWillMount ganchos de ciclo de vida, el servidor todavía está procesando el componente. Por otro lado, almacenamiento local existe como parte de la ventana global del navegador, por lo que solo puede usarlo cuando se representa el componente. Por lo tanto, solo puede acceder a localStorage en el componentDidMount gancho de ciclo de vida. En lugar de llamar a localStorage en el constructor, puede definir un estado vacío y actualizar el estado en componentDidMount cuándo puede comenzar a llamar a localStorage.

constructor() { 
  super()
  this.state = {
    students: [],
    student: undefined
    token: undefined,
    isLoggedIn: undefined
  };
}

componentDidMount() {
  this.login();
  this.setState({
    student: localStorage.getItem('student') || {},
    token: localStorage.getItem('token') || "",
    isLoggedIn: (localStorage.getItem('student' == null)) ? false : true
  });
}

avatar de usuario
ifaruki

Nunca toqué nextjs pero supongo que es equivalente a Nuxt.js. Por lo tanto, realiza la representación del lado del servidor mientras intenta acceder al almacenamiento local en el lado del cliente.

Tendrás que usar componentDidMount() para esto. Aquí un ejemplo

componentDidMount(){
   localStorage.setItem('myCat', 'Tom');
   alert("Tom is in the localStorage");
}

EDITAR:

De lo contrario, podrías probar con process.browser

if (process.browser) {
   localStorage.setItem("token", token);
}

  • no quiero setItem, pero quiero getItem

    – Toni Suwendi

    31 de diciembre de 2019 a las 6:35

Además de lo que dijo @SILENT, esto me funciona

 React.useEffect(() => {
    if (localStorage) {
      const getLocalState = localStorage.getItem("headless");
      console.log("LocalState: ", getLocalState)
    }
  }, []);

El objeto de ventana y el almacenamiento local no estarán disponibles cuando se esté construyendo Nextjs. Por lo tanto, debe verificar si el código se está ejecutando en el navegador. Si está ejecutando ganchos de React, no necesita hacer esto porque los ganchos siempre se ejecutan en el lado del navegador en React.

Simplemente agregue estas dos funciones de utilidad a su proyecto nextjs.

export const isBrowser = (): boolean => {
  return typeof window !== 'undefined'
}

export const nextLocalStorage = (): Storage | void => {
  if (isBrowser()) {
    return window.localStorage
  }
}

entonces puedes usarlo en tu código como este

nextLocalStorage()?.setItem('user', JSON.stringify(user))

avatar de usuario
Ali Askari

Necesitaba leer un token de localStorage en NextJS y agréguelo a un encabezado de instancia de axios. Estaba fuera del componente, así que usé la práctica de IIFE para asegurarme de estar en el cliente:

(function(){
  if(typeof window !== "undefined"){
    AxiosInstance.defaults.headers.common.Authorization = `Bearer ${localStorage.getItem('TOKEN_KEY')}`
  }
})()

avatar de usuario
Azad Ansari

he creado una funcion getLocalStorageItem y llamó a esto en efecto de uso con el nombre de clave requerido. Después de obtener el valor de localStorage, lo guardó en un estado (es decir, currentUser) y lo usó en initialState.

 const [currentUser, setCurrentUser] = useState({});

  const getLocalStorageItem = (key) => {
    return typeof window !== undefined
      ? window.localStorage.getItem(key)
      : null;
  };

  useEffect(() => {
    setCurrentUser({
      token: getLocalStorageItem("token"),
      refreshToken: getLocalStorageItem("refreshToken"),
    });
  }, []);

  const initialState = {
    auth: {
      isLoggedIn: true,
      currentUser: currentUser,
    },
  };

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad