为什么要删除 localStorage 中的 React 状态
Why React state in localStorage is being deleted
我在将状态保存在本地存储中时遇到问题。这是一个简单的待办事项应用程序。添加一个待办事项并刷新后,所有待办事项都被删除了。不知道为什么。相关代码如下:
const [ todos, setTodos ] = useState([])
useEffect(() => {
│ │ console.log('b1:',JSON.parse(localStorage.todos))
│ │ if (localStorage.todos !==null) {
│ │ │ console.log(JSON.parse(localStorage.todos))
│ │ │ setTodos(JSON.parse(localStorage.todos))
│ │ }
│ │ console.log('a1:',JSON.parse(localStorage.todos))
│ }, [])
│ useEffect(() => {
│ │ // if (todos.length > 0) {
│ │ │ console.log('b2:',JSON.parse(localStorage.todos))
│ │ │ localStorage.setItem("todos", JSON.stringify(todos))
│ │ │ console.log('a2:',JSON.parse(localStorage.todos))
│ │ // }
│ }, [todos])
控制台输出(b1 before1,a1 after1 等):
[Log] b1: – [{text: "one", done: false, id: "6c570584b1a"}] (1)
[Log] [{text: "one", done: false, id: "6c570584b1a"}] (1)
[Log] a1: – [{text: "one", done: false, id: "6c570584b1a"}] (1)
[Log] b2: – [{text: "one", done: false, id: "6c570584b1a"}] (1)
[Log] a2: – [] (0)
[Log] b1: – [] (0)
[Log] [] (0)
[Log] a1: – [] (0)
[Log] b2: – [] (0)
[Log] a2: – [] (0)
[Log] b2: – [] (0)
[Log] a2: – [] (0)
useState
钩子是异步的。根据您的代码,您在第一个 useEffect
中调用 setTodos
,然后在不确定 todos
状态是否更新的第二个 useEffect
中调用 todos
状态。
useEffect
也会在组件渲染后第一次触发,即使它有依赖关系(在你的情况下,它是 [todos]
)。
对于可能的修复,您应该在第二次 useEffect
.
中再次更新之前添加一个条件来检查 todos
状态
useEffect(() => {
console.log('b1:',JSON.parse(localStorage.todos))
if (localStorage.todos !==null) {
console.log(JSON.parse(localStorage.todos))
setTodos(JSON.parse(localStorage.todos))
}
console.log('a1:',JSON.parse(localStorage.todos))
}, [])
useEffect(() => {
if (todos && todos.length > 0) {
console.log('b2:',JSON.parse(localStorage.todos))
localStorage.setItem("todos", JSON.stringify(todos))
console.log('a2:',JSON.parse(localStorage.todos))
}
}, [todos])
您实施的 side-effects 不适用于 delete-all 案例。所以我会提出 2 个解决方案
第一个解决方案是使用另一个状态来跟踪第一次加载和下一次加载(比如调用 API)
const [isLoaded, setIsLoaded] = useState(false)
useEffect(() => {
console.log('b1:',JSON.parse(localStorage.todos))
if (localStorage.todos !==null) {
console.log(JSON.parse(localStorage.todos))
setTodos(JSON.parse(localStorage.todos))
setIsLoaded(true)
}
console.log('a1:',JSON.parse(localStorage.todos))
}, [])
useEffect(() => {
if(isLoaded) {
console.log('b2:',JSON.parse(localStorage.todos))
localStorage.setItem("todos", JSON.stringify(todos))
console.log('a2:',JSON.parse(localStorage.todos))
}
}, [todos, isLoaded])
第二个解决方案是在 deleteAll
中更新 localStorage
而不是
useEffect(() => {
console.log('b1:',JSON.parse(localStorage.todos))
if (localStorage.todos !==null) {
console.log(JSON.parse(localStorage.todos))
setTodos(JSON.parse(localStorage.todos))
}
console.log('a1:',JSON.parse(localStorage.todos))
}, [])
useEffect(() => {
if (todos && todos.length > 0) {
console.log('b2:',JSON.parse(localStorage.todos))
localStorage.setItem("todos", JSON.stringify(todos))
console.log('a2:',JSON.parse(localStorage.todos))
}
}, [todos])
function deleteAll() {
setTodos(null)
localStorage.removeItem("todos")
}
我在将状态保存在本地存储中时遇到问题。这是一个简单的待办事项应用程序。添加一个待办事项并刷新后,所有待办事项都被删除了。不知道为什么。相关代码如下:
const [ todos, setTodos ] = useState([])
useEffect(() => {
│ │ console.log('b1:',JSON.parse(localStorage.todos))
│ │ if (localStorage.todos !==null) {
│ │ │ console.log(JSON.parse(localStorage.todos))
│ │ │ setTodos(JSON.parse(localStorage.todos))
│ │ }
│ │ console.log('a1:',JSON.parse(localStorage.todos))
│ }, [])
│ useEffect(() => {
│ │ // if (todos.length > 0) {
│ │ │ console.log('b2:',JSON.parse(localStorage.todos))
│ │ │ localStorage.setItem("todos", JSON.stringify(todos))
│ │ │ console.log('a2:',JSON.parse(localStorage.todos))
│ │ // }
│ }, [todos])
控制台输出(b1 before1,a1 after1 等):
[Log] b1: – [{text: "one", done: false, id: "6c570584b1a"}] (1)
[Log] [{text: "one", done: false, id: "6c570584b1a"}] (1)
[Log] a1: – [{text: "one", done: false, id: "6c570584b1a"}] (1)
[Log] b2: – [{text: "one", done: false, id: "6c570584b1a"}] (1)
[Log] a2: – [] (0)
[Log] b1: – [] (0)
[Log] [] (0)
[Log] a1: – [] (0)
[Log] b2: – [] (0)
[Log] a2: – [] (0)
[Log] b2: – [] (0)
[Log] a2: – [] (0)
useState
钩子是异步的。根据您的代码,您在第一个 useEffect
中调用 setTodos
,然后在不确定 todos
状态是否更新的第二个 useEffect
中调用 todos
状态。
useEffect
也会在组件渲染后第一次触发,即使它有依赖关系(在你的情况下,它是 [todos]
)。
对于可能的修复,您应该在第二次 useEffect
.
todos
状态
useEffect(() => {
console.log('b1:',JSON.parse(localStorage.todos))
if (localStorage.todos !==null) {
console.log(JSON.parse(localStorage.todos))
setTodos(JSON.parse(localStorage.todos))
}
console.log('a1:',JSON.parse(localStorage.todos))
}, [])
useEffect(() => {
if (todos && todos.length > 0) {
console.log('b2:',JSON.parse(localStorage.todos))
localStorage.setItem("todos", JSON.stringify(todos))
console.log('a2:',JSON.parse(localStorage.todos))
}
}, [todos])
您实施的 side-effects 不适用于 delete-all 案例。所以我会提出 2 个解决方案
第一个解决方案是使用另一个状态来跟踪第一次加载和下一次加载(比如调用 API)
const [isLoaded, setIsLoaded] = useState(false)
useEffect(() => {
console.log('b1:',JSON.parse(localStorage.todos))
if (localStorage.todos !==null) {
console.log(JSON.parse(localStorage.todos))
setTodos(JSON.parse(localStorage.todos))
setIsLoaded(true)
}
console.log('a1:',JSON.parse(localStorage.todos))
}, [])
useEffect(() => {
if(isLoaded) {
console.log('b2:',JSON.parse(localStorage.todos))
localStorage.setItem("todos", JSON.stringify(todos))
console.log('a2:',JSON.parse(localStorage.todos))
}
}, [todos, isLoaded])
第二个解决方案是在 deleteAll
中更新 localStorage
而不是
useEffect(() => {
console.log('b1:',JSON.parse(localStorage.todos))
if (localStorage.todos !==null) {
console.log(JSON.parse(localStorage.todos))
setTodos(JSON.parse(localStorage.todos))
}
console.log('a1:',JSON.parse(localStorage.todos))
}, [])
useEffect(() => {
if (todos && todos.length > 0) {
console.log('b2:',JSON.parse(localStorage.todos))
localStorage.setItem("todos", JSON.stringify(todos))
console.log('a2:',JSON.parse(localStorage.todos))
}
}, [todos])
function deleteAll() {
setTodos(null)
localStorage.removeItem("todos")
}