简体   繁体   English

LocalStorage 在提交后不显示数据,并且 state 在刷新时不会持续存在

[英]LocalStorage doesn't display the data after submit and state doesn't persist on refresh

I'm writing a simple todo app and trying to save the data in local-storage.我正在编写一个简单的待办事项应用程序并尝试将数据保存在本地存储中。 I've watched several tutorials considering using localStorage in React and did as they said step by step, and the code seems to be just fine.我看过几个考虑在 React 中使用 localStorage 的教程,并按照他们说的一步一步做,代码似乎还不错。 What seems to be the problem, is the local-storage itself.似乎是问题所在,是本地存储本身。 It should update automatically and display data when I add a todo item using localStorage.setItem(), but it doesn't.当我使用 localStorage.setItem() 添加待办事项时,它应该会自动更新并显示数据,但事实并非如此。 Only when I refresh it (the little refresh button just over the field with key-value pairs in the console in Application -> Local Storage) I can see the key-value pair displayed, so it looks like it has worked.只有当我刷新它(应用程序 - > 本地存储中控制台中带有键值对的字段上方的小刷新按钮)时,我才能看到显示的键值对,所以看起来它已经工作了。 However, even though it seems to keep the data after refreshing it manually, when I refresh the whole page, the data disappear.但是,即使手动刷新后似乎保留了数据,但当我刷新整个页面时,数据消失了。 Below I included most of my code, perhaps I'm missing something and someone will notice the bug.下面我包含了我的大部分代码,也许我遗漏了一些东西,有人会注意到这个错误。 Could someone help?有人可以帮忙吗?

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

  const addTodo = (e) => {
    e.preventDefault();
    if (inputValue.trim() === "") return;
    setTodos([
      ...todos,
      {
        text: inputValue,
        id: uuidv4(),
      },
    ]);

    setInputValue("");
  };

  useEffect(() => {
    const localData = localStorage.getItem("TODO_APP");
    if (localData !== null) setTodos(JSON.parse(localData));
  }, []);

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

Looks like useEffect conflict.看起来像useEffect冲突。 Move the initialization into the useState call.将初始化移到useState调用中。

const [todos, setTodos] = useState(() => {
  const localData = localStorage.getItem("TODO_APP");
  if (localData !== null) return JSON.parse(localData);
  return [];
});

const addTodo = (e) => {
  e.preventDefault();
  if (inputValue.trim() === "") return;
  setTodos([
    ...todos,
    {
      text: inputValue,
      id: uuidv4(),
    },
  ]);

  setInputValue("");
};

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

I will add another slightly modified version.我将添加另一个稍作修改的版本。 Should work:应该管用:

const [todos, setTodos] = useState(JSON.parse(localStorage.getItem('TODO_APP')) || []);

const addTodo = (e) => {
    e.preventDefault();
    
    if (inputValue.trim() !== '') {
        setTodos([
            ...todos,
            {
                text: inputValue,
                id: uuidv4()
            }
        ]);
    }

    setInputValue('');
};

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

Other solutions might work for you, but if you are using React 18 , your code is perfectly fine, the issue was the useEffects called twice on refresh which was resetting localStorage.其他解决方案可能对您有用,但如果您使用的是React 18 ,您的代码非常好,问题是useEffects在刷新时调用了两次,它正在重置 localStorage。 This is a kind of known issue.这是一种已知问题。

You just need to disable StrictMode in the src/index.js file您只需要在src/index.js文件中禁用StrictMode

index.js index.js

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);

reportWebVitals();

I tried to complete the missing part of the component and the final component looks like this:我尝试完成组件的缺失部分,最终组件如下所示:

import { useState, useEffect } from "react";

const Todo = () => {
  const [todos, setTodos] = useState([]);
  const [inputValue, setInputValue] = useState("");

  const onChangeHandler = (e) => {
    setInputValue(e.target.value);
  };

  const addTodo = (e) => {
    e.preventDefault();
    if (inputValue.trim() === "") return;
    setTodos([...todos, { text: inputValue }]);

    setInputValue("");
  };

  useEffect(() => {
    console.log("1st");
    const localData = localStorage.getItem("TODO_APP");
    console.log(localData);
    if (localData.length !== 0) setTodos(JSON.parse(localData));
  }, []);

  useEffect(() => {
    console.log("2nd");
    localStorage.setItem("TODO_APP", JSON.stringify(todos));
  }, [todos]);

  return (
    <form onSubmit={addTodo}>
      <input type="text" value={inputValue} onChange={onChangeHandler}></input>
      <button type="submit">ADD TODO</button>
    </form>
  );
};

export default Todo;

I added console.log() in the code sso you can observe how these useEffects are called on refresh我在代码中添加了console.log() ,所以你可以观察这些useEffects在刷新时是如何被调用的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM