reactjs - React Hooks LocalStorage setState 覆盖元素
问题描述
在将任务存储在本地存储中的情况下,我正在使用 useEffect 处理 React 钩子,因此刷新页面仍将处理列表中的元素。问题是当我试图从 LocalStorage 获取元素并将它们设置为 todos 状态时。它们存在于 localStorage 中,但 todos 状态中的元素只是 localstorage 中的一个。
这是一个处理此问题的组件:
const [todos, setTodos] = useState([]);
const [todo, setTodo] = useState("");
const addTask = (event) => {
event.preventDefault();
let newTask = {
task: todo,
id: Date.now(),
completed: false,
};
setTodos([...todos, newTask]);
setTodo("");
};
const getLocalStorage = () => {
for (let key in localStorage) {
if (!localStorage.hasOwnProperty(key)) {
continue;
}
let value = localStorage.getItem(key);
try {
value = JSON.parse(value);
setTodos({ [key]: value });
} catch (event) {
setTodos({ [key]: value });
}
}
};
const saveLocalStorage = () => {
for (let key in todos) {
localStorage.setItem(key, JSON.stringify(todos[key]));
}
};
useEffect(() => {
getLocalStorage();
}, []);
useEffect(() => {
saveLocalStorage();
}, [saveLocalStorage]);
const testClick = () => {
console.log(todos);
};
return (
<div className="App">
<h1>What would you like to do?</h1>
<TodoForm
todos={todos}
value={todo}
inputChangeHandler={inputChangeHandler}
addTask={addTask}
removeCompleted={removeCompleted}
/>
{/* <TodoList todos={todos} toogleCompleted={toogleCompleted} /> */}
<button onClick={testClick}>DISPLAY TODOS</button>
</div>
);
刷新页面时的第二个问题错误:
除此之外,从本地存储中获取元素后,我无法显示它们。可能我错过了一些愚蠢的小东西,但我停留在这一刻,我想知道是否可以在我犯错误的地方进行小的解释。
解决方案
我认为您正在一起覆盖状态值。您想附加到待办事项状态中存在的内容。您可以使用扩展运算符将待办事项设置为已经存在的所有内容以及新值。
像这样的东西:
setTodos({...todos, [key]: value });
setTodos([...todos, [key]: value ]);
- 请注意,扩展运算符是一个浅克隆。如果您有更深的对象(我认为超过两层),那么请使用 lodash 库中的 cloneDeep 之类的东西。
要查看发生了什么,请更改此块以添加 console.logs
try {
value = JSON.parse(value);
setTodos({ [key]: value });
console.log(todos);
} catch (event) {
console.log('There was an error:', error);
// Should handle the error here rather than try to do what failed again
//setTodos({ [key]: value });
}
编辑:关于您添加的错误。
您正在尝试在对象上使用地图。map 是一个数组函数。
相反,您会将对象转换为数组,然后返回:
const myObjAsArr = Object.entries(todos).map(([k,v]) => {
// Do stuff with key and value
}
const backToObject = Object.fromEntries(myObjAsArr);
更改此项以设置数组(不是对象):
setTodos([...todos, [key]: value ]);
将控制台日志放在任何地方,这样您就可以看到发生了什么。
推荐阅读
- swift - 孩子一旦从父母中移除就不会重新出现
- animation - 有没有办法修改 Flare 中的初始动画状态?
- bash - 只有 shell 脚本中的最后一个变量正确且完整地回显
- android - 当我的应用程序打开时永远做一个任务 - 怎么做?
- javascript - 如果 HTML 标签不是兄弟元素或父元素,如何定位和重命名它?
- php - 是否有任何功能/代码可以防止在数据库中保存重复值?
- python - 使用索引和子索引将值分配给 numpy 数组
- javascript - 单击注册页面按钮时没有响应
- python - 如何最好地为我的树类编写一个 __str__ 方法?
- maven - 如何让 Maven 只做我的自定义配置文件?