使用LocalStorage反应钩子

时间:2020-07-15 02:21:48

标签: reactjs react-hooks local-storage

使用react钩子添加项目后,我正在尝试同步本地存储。

我有以下代码

function App() {

  const [currentStorage, SyncWithLocalStorage] = useState(localStorage || {});

  window.addEventListener("storage", e => {
    SyncWithLocalStorage(localStorage);
  });

  return (
    <div className="App">
      <Note onAddNewNote={AddNoteToLocalStorage}></Note>
      <div>
        {
          Object.keys(currentStorage).map(
            key => <Postit key={key} input={currentStorage.getItem(key)}></Postit>
          )
        }
      </div>
    </div>
  );
}

function AddNoteToLocalStorage(note) {
  const { id, input } = note;
  localStorage.setItem(id, input);
  window.dispatchEvent(new Event('storage'));
}

export default App;

我添加了 window.dispatchEvent 行,因为存储事件未在chrome中触发,因此我必须手动执行。

我的想法是一旦执行AddNoteToLocalStorage(note)方法,它应该检测到本地存储的更改(正在执行),然后更新状态并触发组件的重新渲染为了显示新的添加。现在不起作用。我需要刷新页面以获取新添加的集合。

1 个答案:

答案 0 :(得分:1)

进行以下更改,它应该可以工作。

  • 使用useEffect并添加eventListener ONCE。卸载后还删除监听器
  • 更新状态时,请确保spread会更改对象引用并导致重新渲染

Working demo of your code

重构代码段

function App() {
  const [currentStorage, SyncWithLocalStorage] = useState(localStorage || {});
  const eventListenerFun = e => {
    console.log("localStorage", { ...localStorage });
    SyncWithLocalStorage({ ...localStorage }); //<----spread it which will cause refrence to change
  };
  useEffect(() => {
    window.addEventListener("storage", eventListenerFun);

    return () => window.removeEventListener("storage", eventListenerFun);
  }, []);

  return (
    <div className="App">
      <button
        onClick={() =>
          AddNoteToLocalStorage({ id: Date.now(), input: "hello" })
        }
      >
        add note{" "}
      </button>
      <div>
        hi
        {currentStorage &&
          Object.keys(currentStorage).map(key => (
            <div key={key}>{currentStorage[key]}</div>
          ))}
      </div>
    </div>
  );
}

function AddNoteToLocalStorage(note) {
  const { id, input } = note;
  localStorage.setItem(id, input);
  window.dispatchEvent(new Event("storage"));
}

export default App;