In reactjs and nextjs constructor getting Reference Error: localstorage is not defined
In reactjs and nextjs constructor getting Reference Error: localstorage is not defined
我在 reactjs 中制作系统 jsonwebtoken 并使用 nextjs。当我 运行 浏览器中的 localStorage 代码未定义时,我发现了问题。
这是我在文件中的代码 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)
})
}
并显示错误 localStorage is not defined
我从未接触过 nextjs,但我猜它相当于 Nuxt.js。因此,当您尝试在客户端访问本地存储时,它会进行服务器端渲染。
为此您需要使用 componentDidMount()
。举个例子
componentDidMount(){
localStorage.setItem('myCat', 'Tom');
alert("Tom is in the localStorage");
}
编辑:
否则你可以试试 process.browser
if (process.browser) {
localStorage.setItem("token", token);
}
在 constructor
和 componentWillMount
生命周期挂钩上,服务器仍在渲染组件。另一方面,localStorage 作为浏览器 Window 全局的一部分存在,因此您只能在呈现组件时使用它。因此,您只能在 componentDidMount
生命周期挂钩上访问 localStorage。您可以定义一个空状态,并在可以开始调用 localStorage 时更新 componentDidMount
上的状态,而不是在构造函数上调用 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
});
}
正如大家已经提到的,NextJS 同时在客户端和服务器上运行。在服务器上,没有 localStorage
,因此 undefined
错误。
但是,另一种解决方案是在访问 localStorage
之前检查服务器上的 nextjs 是否 运行。即
const ISSERVER = typeof window === "undefined";
if(!ISSERVER) {
// Access localStorage
...localStorage.get...
}
除了@SILENT 所说的,这对我有用
React.useEffect(() => {
if (localStorage) {
const getLocalState = localStorage.getItem("headless");
console.log("LocalState: ", getLocalState)
}
}, []);
Window 对象和 Localstorage 在 Nextjs 构建时将不可用。所以你需要在浏览器中检查代码是否为运行。如果你在 React hooks 中 运行 你不需要这样做,因为在 React 中 hooks 总是 运行 浏览器端。
只需将这两个实用函数添加到您的 nextjs 项目中即可。
export const isBrowser = (): boolean => {
return typeof window !== 'undefined'
}
export const nextLocalStorage = (): Storage | void => {
if (isBrowser()) {
return window.localStorage
}
}
然后你可以像这样在你的代码中使用它
nextLocalStorage()?.setItem('user', JSON.stringify(user))
我需要在 NextJS 中从 localStorage
读取一个令牌并将其添加到 axios 实例 header。它在组件之外,所以我使用 IIFE 实践来确保在客户端中:
(function(){
if(typeof window !== "undefined"){
AxiosInstance.defaults.headers.common.Authorization = `Bearer ${localStorage.getItem('TOKEN_KEY')}`
}
})()
我创建了一个函数 getLocalStorageItem 并在 useEffect 中使用所需的键名调用了它。从 localStorage 获取值后,将其保存在状态(即 currentUser)中并在 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,
},
};
我在 reactjs 中制作系统 jsonwebtoken 并使用 nextjs。当我 运行 浏览器中的 localStorage 代码未定义时,我发现了问题。
这是我在文件中的代码 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)
})
}
并显示错误 localStorage is not defined
我从未接触过 nextjs,但我猜它相当于 Nuxt.js。因此,当您尝试在客户端访问本地存储时,它会进行服务器端渲染。
为此您需要使用 componentDidMount()
。举个例子
componentDidMount(){
localStorage.setItem('myCat', 'Tom');
alert("Tom is in the localStorage");
}
编辑:
否则你可以试试 process.browser
if (process.browser) {
localStorage.setItem("token", token);
}
在 constructor
和 componentWillMount
生命周期挂钩上,服务器仍在渲染组件。另一方面,localStorage 作为浏览器 Window 全局的一部分存在,因此您只能在呈现组件时使用它。因此,您只能在 componentDidMount
生命周期挂钩上访问 localStorage。您可以定义一个空状态,并在可以开始调用 localStorage 时更新 componentDidMount
上的状态,而不是在构造函数上调用 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
});
}
正如大家已经提到的,NextJS 同时在客户端和服务器上运行。在服务器上,没有 localStorage
,因此 undefined
错误。
但是,另一种解决方案是在访问 localStorage
之前检查服务器上的 nextjs 是否 运行。即
const ISSERVER = typeof window === "undefined";
if(!ISSERVER) {
// Access localStorage
...localStorage.get...
}
除了@SILENT 所说的,这对我有用
React.useEffect(() => {
if (localStorage) {
const getLocalState = localStorage.getItem("headless");
console.log("LocalState: ", getLocalState)
}
}, []);
Window 对象和 Localstorage 在 Nextjs 构建时将不可用。所以你需要在浏览器中检查代码是否为运行。如果你在 React hooks 中 运行 你不需要这样做,因为在 React 中 hooks 总是 运行 浏览器端。
只需将这两个实用函数添加到您的 nextjs 项目中即可。
export const isBrowser = (): boolean => {
return typeof window !== 'undefined'
}
export const nextLocalStorage = (): Storage | void => {
if (isBrowser()) {
return window.localStorage
}
}
然后你可以像这样在你的代码中使用它
nextLocalStorage()?.setItem('user', JSON.stringify(user))
我需要在 NextJS 中从 localStorage
读取一个令牌并将其添加到 axios 实例 header。它在组件之外,所以我使用 IIFE 实践来确保在客户端中:
(function(){
if(typeof window !== "undefined"){
AxiosInstance.defaults.headers.common.Authorization = `Bearer ${localStorage.getItem('TOKEN_KEY')}`
}
})()
我创建了一个函数 getLocalStorageItem 并在 useEffect 中使用所需的键名调用了它。从 localStorage 获取值后,将其保存在状态(即 currentUser)中并在 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,
},
};