React Todo List本地存储失效排查:使用localStorage后待办项刷新丢失问题求助
问题分析与解决方案
你遇到的问题核心在于组件初始挂载时,第二个useEffect会将空数组写入localStorage,直接覆盖掉之前存储的待办事项。
具体来说:
- 组件初始化时,
todos的初始值是[] - 第二个
useEffect依赖todos,所以会在组件挂载后立即执行,把空数组存入localStorage - 第一个
useEffect虽然会读取localStorage里的旧数据,但setTodos是异步的,还没等状态更新,第二个useEffect已经把空数组覆盖进去了,导致下次刷新时读不到旧数据
另外,你的toggleTodo函数直接修改了原数组里的对象,虽然能触发更新,但不符合React的不可变数据原则,可能会引发一些难以排查的问题,也建议一起优化。
修复步骤
1. 阻止初始挂载时的localStorage写入
我们可以添加一个状态变量标记是否是首次渲染,让第二个useEffect只在todos真正发生变更时才执行保存操作:
import React, { useState, useRef, useEffect } from "react"; import TodoList from "./TodoList" const { v4: uuidv4 } = require('uuid'); const LOCAL_STORAGE_KEY = 'todoApp.todos' function App() { const [todos, setTodos] = useState([]) const doAccess = useRef() // 标记是否为首次渲染 const [isFirstRender, setIsFirstRender] = useState(true) useEffect(() => { const storedTodos = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY)) if (storedTodos) setTodos(storedTodos) }, []) useEffect(() => { // 首次渲染时跳过保存 if (isFirstRender) { setIsFirstRender(false) return } localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(todos)) }, [todos, isFirstRender]) // 优化toggleTodo,遵循不可变数据原则 function toggleTodo(id){ setTodos(prevTodos => prevTodos.map(todo => todo.id === id ? {...todo, complete: !todo.complete} : todo ) ) } function handleAddTodo(e){ const name= doAccess.current.value if (name === '') return setTodos (prevTodos =>{ return [...prevTodos, {id: uuidv4(), name: name, complete: false}] }) // 清空输入框 doAccess.current.value = '' } // 补充Clear Todo功能 function handleClearTodos() { setTodos(prevTodos => prevTodos.filter(todo => !todo.complete)) } return ( <> <TodoList todos={todos} toggleTodo={toggleTodo}/> <input ref={doAccess} type="text" /> <button onClick={handleAddTodo}>Add Todo</button> <button onClick={handleClearTodos}>Clear Completed Todos</button> <div>{todos.filter(todo => !todo.complete).length} Todos Left</div> </> ) } export default App;
2. 额外优化点
- 优化了
toggleTodo函数,使用map创建新数组和新的todo对象,完全遵循不可变数据原则,避免直接修改原状态 - 补充了
Clear Completed Todos的功能实现 - 添加了清空输入框的逻辑,提升用户体验
- 修复了剩余待办数量的计算逻辑
内容的提问来源于stack exchange,提问作者ipshita sett
相关产品推荐
相关产品推荐

