Mauro Alvarez
Mauro Alvarez

Reputation: 612

React Hooks with LocalStorage

I'm trying to sync the localstorage after adding an item using react hooks.

I have the following code

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;

I added the line window.dispatchEvent because storage event is not triggering in chrome, so I have to manually do it.

My idea is once the AddNoteToLocalStorage(note) method is executed, it should detect a change in the localstorage (which is doing now) then update the state and trigger a re render of the component in order to show the new addition. This is not working now. I need to refresh the page to get the newly added collection.

Upvotes: 0

Views: 2024

Answers (1)

gdh
gdh

Reputation: 13682

Make the following changes, it should work.

  • use useEffect and add eventListener ONCE. Also remove the listener upon unmount
  • when updating state, make sure to spread which changes the object reference and causes the re-render

Working demo of your code

Refactored Code snippet

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;

Upvotes: 1

Related Questions