如何在 Next.js 中使用本地存储
在 Next.js 中使用本地存储时,您是否收到以下错误?
ReferenceError: localStorage is not defined
在本文中,我们将了解如何在 Next.js 中使用本地存储
项目设立
使用以下命令创建 Next.js 应用程序:
npx create-next-app next-local-storage
index.js
使用以下代码更新:
import { useState } from "react"
export default function Home() {
let value
// Get the value from local storage if it exists
value = localStorage.getItem("favoriteNumber") || ""
// Set the value received from the local storage to a local state
const [favoriteNumber, setFavoriteNumber] = useState(value)
// When user submits the form, save the favorite number to the local storage
const saveToLocalStorage = e => {
e.preventDefault()
localStorage.setItem("favoriteNumber", favoriteNumber)
}
return (
<div>
<label htmlFor="number">Your favorite number</label>
<form onSubmit={saveToLocalStorage}>
<input
id="number"
value={favoriteNumber}
onChange={e => setFavoriteNumber(e.target.value)}
/>
<input type="submit" value="Save" />
</form>
</div>
)
}
现在如果你运行代码,你将会得到以下错误:
为什么会出现这个错误?
发生错误的原因是代码在服务器中编译(在本地主机或生产中的服务器端渲染中),localStorage
对象不存在。
修复
有多种方法可以修复它。
检查窗口是否已定义
localStorage
是对象内部的对象window
。window 对象不会在服务器中定义,因此 localStorage 代码也不会在服务器中执行。
if (typeof window !== "undefined") {
value = localStorage.getItem("favoriteNumber") || ""
}
使用 try-catch 块
我们可以使用 try-catch 块来包围访问localStorage
:
try {
value = localStorage.getItem("favoriteNumber") || ""
} catch (error) {}
使用 useEffect 钩子
您可以使用useEffect hook来获取 localStorage 内容。useEffect hook 不会在服务器中运行,因此不会出现错误。
import { useEffect, useState } from "react"
export default function Home() {
// Set the value received from the local storage to a local state
const [favoriteNumber, setFavoriteNumber] = useState("")
useEffect(() => {
let value
// Get the value from local storage if it exists
value = localStorage.getItem("favoriteNumber") || ""
setFavoriteNumber(value)
}, [])
// When user submits the form, save the favorite number to the local storage
const saveToLocalStorage = e => {
e.preventDefault()
localStorage.setItem("favoriteNumber", favoriteNumber)
}
return (
<div>
<label htmlFor="number">Your favorite number</label>
<form onSubmit={saveToLocalStorage}>
<input
id="number"
value={favoriteNumber}
onChange={e => setFavoriteNumber(e.target.value)}
/>
<input type="submit" value="Save" />
</form>
</div>
)
}
使用自定义钩子
您也可以使用自定义钩子来访问本地存储
import { useState } from "react"
const useLocalStorage = (key, initialValue) => {
const [state, setState] = useState(() => {
// Initialize the state
try {
const value = window.localStorage.getItem(key)
// Check if the local storage already has any values,
// otherwise initialize it with the passed initialValue
return value ? JSON.parse(value) : initialValue
} catch (error) {
console.log(error)
}
})
const setValue = value => {
try {
// If the passed value is a callback function,
// then call it with the existing state.
const valueToStore = value instanceof Function ? value(state) : value
window.localStorage.setItem(key, JSON.stringify(valueToStore))
setState(value)
} catch (error) {
console.log(error)
}
}
return [state, setValue]
}
export default useLocalStorage
在中index.js
,您可以按如下方式使用它:
import useLocalStorage from "@/hooks/useLocalStorage"
import { useState } from "react"
export default function Home() {
// Get the value from local storage if it exists
const [value, setValue] = useLocalStorage("favoriteNumber", "")
// Set the value received from the local storage to a local state
const [favoriteNumber, setFavoriteNumber] = useState(value)
// When user submits the form, save the favorite number to the local storage
const saveToLocalStorage = e => {
e.preventDefault()
setValue(favoriteNumber)
}
return (
<div>
<label htmlFor="number">Your favorite number</label>
<form onSubmit={saveToLocalStorage}>
<input
id="number"
value={favoriteNumber}
onChange={e => setFavoriteNumber(e.target.value)}
/>
<input type="submit" value="Save" />
</form>
</div>
)
}