localStorage 数据在页面重新加载时不断重置 - React js

localStorage data keeps resetting on page reload - React js

错误:localStorage 数据在页面重新加载时不断重置。尽管之前已更新到 localStorage。

如果我添加新的待办事项,它会添加到 localStorage。但是更新的项目在页面重新加载后消失了,我得到了初始状态值(todos)。

源代码:https://www.codepile.net/pile/J9L4xL9g

// App.js
// Error: localStorage data keeps resetting on page reload. Despite of being updated to localStorage before.
// If I add new todo item, it is added to localStorage. But it disappears after page reload and I get initial state value(todos). I don't know where is the problem here!

import { useState, useEffect } from "react";

function App() {
  const [todos, setTodos] = useState([{ id: 123, text: "todo 1 demo" }]);
  const [todo, setTodo] = useState("");

  function handleSubmit(e) {
    e.preventDefault();

    const newTodo = {
      id: new Date().getTime(),
      text: todo
    };

    setTodos([...todos].concat(newTodo));
    setTodo("");
  }

  useEffect(() => {
    const temp = localStorage.getItem("todos");
    const loadedTodos = JSON.parse(temp);
    if (loadedTodos) {
      setTodos(loadedTodos);
    }
  }, []);

  useEffect(() => {
    localStorage.setItem("todos", JSON.stringify(todos));
  }, [todos]);

  return (
    <div className="App">
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          onChange={(e) => setTodo(e.target.value)}
          value={todo}
        />
        <button>Add todo</button>
      </form>

      {todos.map((todo) => (
        <div key={todo.id}>
          <div>{todo.text}</div>
        </div>
      ))}
    </div>
  );
}

export default App;

您需要在 useEffect 函数中检查 todos 数组的长度。

useEffect 的回调函数将在每次更改依赖更新时触发

因此,在第一次使用初始值设置待办事项状态时,会触发 useEffect 回调,这就是每次重新加载后都会丢失数据的原因

  useEffect(() => {
    if (todos.length > 1) localStorage.setItem("todos", JSON.stringify(todos));
  }, [todos]);

您可以通过添加这个简单的 if 条件来解决您的问题

您 运行 遇到的问题是,与设置它的时间相比,您 useEffect 从存储中设置待办事项的时机不佳。

因此,与其使用效果来获取待办事项,不如让它们与状态同步。这种带有函数参数的 useState 样式允许您为初始创建状态进行更昂贵的计算,因此该函数只会在初始组件安装时被调用。

  const [todos, setTodos] = useState(
    () =>
      JSON.parse(localStorage.getItem("todos")) || [
        { id: 123, text: "todo 1 demo" }
      ]
  );
  useEffect(() => {
    localStorage.setItem("todos", JSON.stringify(todos));
  }, [todos]);

这样就可以去掉多余的效果,防止在初始代码运行和从本地存储中抓取待办事项之间闪现不正确的UI

https://codesandbox.io/s/eloquent-babycat-z86dts?file=/src/App.js