LocalStorage保存了我的数据,但是刷新重置后将其清空
我有问题,我需要您帮助我理解它。我正在使用ReactJS,并且正在构建一个简单的Crud Todo应用程序。我想将我的戒酒存储在本地存储中。 数据保存在那里,我可以看到它,但是刷新后,它将清空我的本地存储。
我在做什么错? 我注意到的是,从我第一次打开应用程序(第一次渲染)时,本地存储在不添加todo的情况下创建存储空间。
我可以错过我的代码中的一些东西,以使其重置或在渲染页面时将其清空?
import React, { useState, useEffect } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faCheck,
faPen,
faPlus,
faTrashCan,
} from "@fortawesome/free-solid-svg-icons";
import "./App.css";
import { faCircleCheck } from "@fortawesome/free-regular-svg-icons";
function App() {
const [todos, setTodos] = useState([]);
const [todo, setTodo] = useState("");
const [todoEditing, setTodoEditing] = useState(null);
const [editingText, setEditingText] = useState("");
useEffect(() => {
const json = window.localStorage.getItem("todos");
const loadedTodos = JSON.parse(json);
if (loadedTodos) {
setTodos(loadedTodos);
}
}, []);
useEffect(() => {
const json = JSON.stringify(todos);
window.localStorage.setItem("todos", json);
}, [todos]);
function handleSubmit(e) {
e.preventDefault();
const newTodo = {
id: new Date().getTime(),
text: todo,
completed: false,
};
setTodos([...todos].concat(newTodo));
setTodo("");
}
function deleteTodo(id) {
const updatedTodos = [...todos].filter((todo) => todo.id !== id);
setTodos(updatedTodos);
}
function toggleComplete(id) {
let updatedTodos = [...todos].map((todo) => {
if (todo.id === id) {
todo.completed = !todo.completed;
}
return todo;
});
setTodos(updatedTodos);
}
function submitEdits(id) {
const updatedTodos = [...todos].map((todo) => {
if (todo.id === id) {
todo.text = editingText;
}
return todo;
});
setTodos(updatedTodos);
setTodoEditing(null);
}
return (
<div className="App">
<div className="app-container">
<div className="todo-header">
<form onSubmit={handleSubmit}>
<input
type="text"
name="todo-input-text"
placeholder="write a todo..."
onChange={(e) => {
setTodo(e.target.value);
}}
value={todo}
/>
<button>
<FontAwesomeIcon icon={faPlus} />
</button>
</form>
</div>
<div className="todo-body">
{todos.map((todo) => {
return (
<div className="todo-wrapper" key={todo.id}>
{todo.id === todoEditing ? (
<input
className="edited-todo"
type="text"
onChange={(e) => setEditingText(e.target.value)}
/>
) : (
<p className={todo.completed ? "completed" : "uncompleted"}>
{todo.text}
</p>
)}
<div className="todo-buttons-wrapper">
<button onClick={() => toggleComplete(todo.id)}>
<FontAwesomeIcon icon={faCircleCheck} />
</button>
{todo.id === todoEditing ? (
<button onClick={() => submitEdits(todo.id)}>
<FontAwesomeIcon icon={faCheck} />
</button>
) : (
<button onClick={() => setTodoEditing(todo.id)}>
<FontAwesomeIcon icon={faPen} />
</button>
)}
<button
onClick={() => {
deleteTodo(todo.id);
}}
>
<FontAwesomeIcon icon={faTrashCan} />
</button>
</div>
</div>
);
})}
</div>
</div>
</div>
);
}
export default App;
I have a problem and I need you to help me understand it. I am using ReactJS and I am building a simple CRUD Todo App. I Want to store my todos in local storage.
The data is saved there and I can see it but after the refresh it is emptying my local storage.
What am I doing wrong?
Something that I notice is that from the first time when I open the app (first rendering), local storage is creating the storage space without adding a todo.
Could I have missed something in my code that makes it reset it or empty it when the page is rendered?
import React, { useState, useEffect } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faCheck,
faPen,
faPlus,
faTrashCan,
} from "@fortawesome/free-solid-svg-icons";
import "./App.css";
import { faCircleCheck } from "@fortawesome/free-regular-svg-icons";
function App() {
const [todos, setTodos] = useState([]);
const [todo, setTodo] = useState("");
const [todoEditing, setTodoEditing] = useState(null);
const [editingText, setEditingText] = useState("");
useEffect(() => {
const json = window.localStorage.getItem("todos");
const loadedTodos = JSON.parse(json);
if (loadedTodos) {
setTodos(loadedTodos);
}
}, []);
useEffect(() => {
const json = JSON.stringify(todos);
window.localStorage.setItem("todos", json);
}, [todos]);
function handleSubmit(e) {
e.preventDefault();
const newTodo = {
id: new Date().getTime(),
text: todo,
completed: false,
};
setTodos([...todos].concat(newTodo));
setTodo("");
}
function deleteTodo(id) {
const updatedTodos = [...todos].filter((todo) => todo.id !== id);
setTodos(updatedTodos);
}
function toggleComplete(id) {
let updatedTodos = [...todos].map((todo) => {
if (todo.id === id) {
todo.completed = !todo.completed;
}
return todo;
});
setTodos(updatedTodos);
}
function submitEdits(id) {
const updatedTodos = [...todos].map((todo) => {
if (todo.id === id) {
todo.text = editingText;
}
return todo;
});
setTodos(updatedTodos);
setTodoEditing(null);
}
return (
<div className="App">
<div className="app-container">
<div className="todo-header">
<form onSubmit={handleSubmit}>
<input
type="text"
name="todo-input-text"
placeholder="write a todo..."
onChange={(e) => {
setTodo(e.target.value);
}}
value={todo}
/>
<button>
<FontAwesomeIcon icon={faPlus} />
</button>
</form>
</div>
<div className="todo-body">
{todos.map((todo) => {
return (
<div className="todo-wrapper" key={todo.id}>
{todo.id === todoEditing ? (
<input
className="edited-todo"
type="text"
onChange={(e) => setEditingText(e.target.value)}
/>
) : (
<p className={todo.completed ? "completed" : "uncompleted"}>
{todo.text}
</p>
)}
<div className="todo-buttons-wrapper">
<button onClick={() => toggleComplete(todo.id)}>
<FontAwesomeIcon icon={faCircleCheck} />
</button>
{todo.id === todoEditing ? (
<button onClick={() => submitEdits(todo.id)}>
<FontAwesomeIcon icon={faCheck} />
</button>
) : (
<button onClick={() => setTodoEditing(todo.id)}>
<FontAwesomeIcon icon={faPen} />
</button>
)}
<button
onClick={() => {
deleteTodo(todo.id);
}}
>
<FontAwesomeIcon icon={faTrashCan} />
</button>
</div>
</div>
);
})}
</div>
</div>
</div>
);
}
export default App;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果像这样在localstorage中可用,则应从localstorage上加载dodos,
然后您不必在
useffect
中使用settodos(ladeedtodos)突变状态。只需从代码中删除此使用效果:
您可以在工作 codesandbox 也是如此。
You should be loading todos from localStorage on the Component mount if they are available in localStorage like this,
And then you don't have to mutate the state using setTodos(loadedTodos) in the
useEffect
.Just remove this useEffect , from the code:
You can check this in the working CodeSandbox as well.
我认为您的第二次使用效果使其重置。
将使用效果逻辑移动到单独的函数。
而不是调用
settodos
,请调用该功能,更新存储,然后从该功能调用settodos
。I think your second useEffect is causing it to reset.
Move that the useEffect logic to a separate function.
And instead of calling
setTodos
, call that function, update the storage, and then callsetTodos
from that function.如果您使用回调函数调用Settodos函数,并将其类似的传播操作员起作用:
If you call the setTodos function with a callback function and spread operator like this it should work: