javascript 为什么useEffect不从本地存储设置项?

dzjeubhm  于 2023-03-21  发布在  Java
关注(0)|答案(3)|浏览(112)

我最近开始学习web开发,这让我头疼。我做了一个简单的todo应用程序,你可以添加一个id和值的项目到数组中,并从数组中删除该项目。现在我希望每当网站刷新时,我希望项目都在那里。我做了一个测试数组,出于某种原因,当刷新时,它可以工作,但不适用于data

const [items, setItems] = useState([]);
  const testarr = [{id: 1, value: "a"}, {id: 2, value: "b"}];

  useEffect(() => {
    const data = JSON.parse(localStorage.getItem("items"));
    console.log(data);
    // setItems(testarr);
    setItems(data);
  }, [])

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

我想到的是:

useEffect(() => {
    const data = JSON.parse(localStorage.getItem("items"));
    data.forEach(element => {
      setItems(oldarr => [...oldarr, element]);
    });
  }, [])

问题是,如果我不断刷新站点的速度足够快,最终数组将再次变为空。我不明白,当刷新时,它记录data就可以了,但当我想记录setItems(data)时,它就不工作了。有人知道为什么它会这样吗?

cig3rfwq

cig3rfwq1#

setState是一个异步函数,这意味着下面的代码片段将始终在项目从“setItems(data)”接收数据之前以空数组的形式运行。

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

也许,你可以在存储之前检查items是否不是空数组

useEffect(() => {
       if (Array.isArray(items) && items.length > 0) {
           window.localStorage.setItem("items", JSON.stringify(items));
       }
    }, [items]);
9gm1akwq

9gm1akwq2#

请尝试不带窗口的localStorage对象
例如:

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

i7uq4tfw3#

问题

下面的useEffect在每次items发生变化时都会运行,但在挂载时也会运行。在挂载时,items等于[],即一开始给useState的数组。这就是为什么localStorage被设置为[]

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

溶液

解决此问题的一种方法是如下所示更改状态定义,因此当localStorage中有数据时,您可以选择它:

const [items, setItems] = useState(!localStorage.getItem("items") ? [] : JSON.parse(localStorage.getItem("items")));

此时,您可以删除用于从localStorage获取数据并将其提供给setItems的两个useEffect

相关问题