【问题标题】:Key Value pair appears in LocalStorage, but doesn't persist after refresh despite having JSON stringify/setItem/etc键值对出现在 LocalStorage 中,但刷新后不会持续存在,尽管有 JSON stringify/setItem/etc
【发布时间】:2021-07-23 18:26:16
【问题描述】:

我构建了一个 Todo 应用程序,它运行顺畅,但 localStorage 在刷新后不会持续存在这一事实。 localStorage 命令以前在我的事件处理程序较少时有效,但现在似乎在某个地方,存储被擦除了。我已经尝试过我在这里看到的基本解决方案,但似乎有一些独特的东西会导致错误。这是我的保存/获取功能:

保存:

const saveLocalTodos = () => {
  localStorage.setItem("todos", JSON.stringify(todos));
};

获取:

const getLocalTodos = () => {
  if (localStorage.getItem("todos") === null) {
    localStorage.setItem("todos", JSON.stringify(todos));
  } else {
    let localTodo = JSON.parse(
      localStorage.getItem("todos", JSON.stringify(todos))
    );
    setTodos(localTodo);
  }
};

实际上,通过将“待办事项”项设置为字符串化数组待办事项(当添加新的待办事项/完成状态更改/项目已加星标/等时,它可以工作并显示在本地存储中)来保存该过程。 useState函数如下:

useEffect(() => {
  filteredTodosHandler();
  saveLocalTodos();
}, [todos, status, starredToggle]);

所以就像我说的,当 todos 数组改变、可点击状态过滤器改变或星号复选框被点击时调用。这些都不会破坏 localStorage。下面是 getLocalTodos 的 useEffect:

useEffect(() => {
  getLocalTodos();
}, []);

如果我理解正确,一个空数组大致意味着它在页面刷新时被调用。问题是当我刷新时,我总是得到一个空数组。我试过添加“窗口”。在 localStorage 函数调用的开头,将 e.preventDefault 添加到 saveLocalTodos 案例中涉及的事件处理程序中,并确保我将数组转换为字符串化对象。似乎没有任何效果。我在 GitHub 存储库中有一份该应用程序的副本,并通过 Firebase 托管,如果这样可以增加更多洞察力的话。

【问题讨论】:

  • localstorage 是否在刷新时完全被擦除/清空,或者只是像 [] 一样清空数组?
  • 它变成了一个带有“todos”键的空数组。我自己也想知道这个问题,似乎问题是 也许 与 if 语句中的错误处理有关?
  • 然后useEffect 在您刷新时更改初始渲染时的本地存储。查看useEffect的依赖数组
  • 埃姆雷听起来不错。下班后我会回来解决这个问题的。

标签: javascript reactjs local-storage


【解决方案1】:

你会这样定义待办事项吗?

const [todos, setTodos] = useState([]);

还有加载块

useEffect(() => {
  getLocalTodos();
}, []);

在保存块之后进行

useEffect(() => {
  filteredTodosHandler();
  saveLocalTodos();
}, [todos, status, starredToggle]);

在您的代码中?

如果是这样,那么保存效果saveLocalTodos();会在加载效果getLocalTodos()之前被调用,当页面重新加载时,它会从useState([])中保存[]的默认值;到本地存储,然后由加载效果加载。 这就是它可能会被消灭的方式。

为了测试它尝试切换useEffect 块的顺序。还要添加一些日志来检查这些块的运行顺序。

如果可行,您仍然应该更改设计,如果useEffect 的声明顺序很重要,那真的很糟糕,有人(甚至您)可能稍后会更改它并重新引入问题。

【讨论】:

  • 待办事项状态设置为:const [todos, setTodos] = useState([]); 我还没有尝试记录 useState 订单,但我会尝试。谢谢
  • 将 [] 更改为 null
  • 作为设计更改的建议 - 您可以像这样 useState(getLocalTodos()) 在调用 useState 之前加载 todos 并修改 getLocalTodos 以返回结果值而不是调用 setTodos(localTodo);
  • 当我记录它时,它看起来就像在刷新时,一切都被调用了。这件事看起来将是一个巨大的混乱。我现在需要去上班,但显然有很多事情需要解决。希望这只是重写一些 useEffect 语句的问题,这样我就没有一个循环,它似乎在刷新时 saveTodos -> getTodos -> saveTodos。我不知道教练做的时候架构是不是有问题,但现在肯定是。
  • 它看起来不太乱。我猜保存块会在页面重新加载时被调用两次。只需去掉加载效果useEffect(() => { getLocalTodos(); }, []);,调用useState时直接加载
猜你喜欢
  • 1970-01-01
  • 2018-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-15
  • 1970-01-01
  • 1970-01-01
  • 2022-12-06
相关资源
最近更新 更多