就像标题所说,我设置的 localStorage 注册了对
todoList
数组所做的更改,并且 JSON.stringify
是它;但是,每当我刷新页面时,数组都会返回默认的 []
状态。
const LOCAL_STORAGE_KEY = "task-list"
function TodoList() {
const [todoList, setTodoList] = useState([]);
useEffect(() => {
const storedList = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY));
if (storedList) {
setTodoList(storedList);
}
}, []);
useEffect(() => {
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(todoList));
}, [todoList]);
当您重新加载应用程序/组件时,两个效果都会运行,并且 React 状态更新是异步处理的,因此它会在处理状态更新之前拾取保存到 localStorage 的空数组状态。设置初始
todoList
状态值时直接从localStorage读取即可。
示例:
const LOCAL_STORAGE_KEY = "task-list"
function TodoList() {
const [todoList, setTodoList] = useState(() => {
return JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY)) || []
});
useEffect(() => {
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(todoList));
}, [todoList]);
...
上述解决方案并非在所有情况下都有效。相反,请在
localStorage.setItem
行前面添加一个条件,以防止出现 [] 情况。
//does not work in all cases (such as localhost)
function TodoList() {
const [todoList, setTodoList] = useState(() => {
return JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY)) || []
});
//use conditional instead
useEffect(() => {
if (todoList.length > 0) {localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(todoList))}
}, [todoList])
您的 React 版本高于 v18,它实现了
useEffect(() => {
const storedList = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY));
if (storedList) {
setTodoList(storedList);
}
}, []);
不起作用,因为它检测到潜在的问题。如果你删除了
本文演示了如何避免在首次渲染时运行
useEffect
钩子。
这是您修改后的代码,不会在初始渲染时覆盖 localStorage:
import { useState, useEffect, useRef } from "react";
const LOCAL_STORAGE_KEY = "task-list"
const isMounted = useRef(false);
function TodoList() {
const [todoList, setTodoList] = useState([]);
useEffect(() => {
const storedList = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY));
if (storedList) {
setTodoList(storedList);
}
}, []);
useEffect(() => {
// don't store on initial render
if (isMounted.current) {
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(todoList));
} else {
isMounted.current = true;
}
}, [todoList]);
}