soyguijarro / react-storage-hooks

React hooks for persistent state
https://npm.im/react-storage-hooks
MIT License
166 stars 18 forks source link

[BUG] State not syncing with React 17 #49

Open PabloLION opened 2 years ago

PabloLION commented 2 years ago

What's the problem

When having multiple instance with same localStorage entry, only one of them will sync with localStorage.

Expected behavior

All instances will sync with localStorage as it is said in the documentation.

Automatically stringifies and parses values coming and going to storage, keeps state in sync between tabs by listening to storage events and handles non-straightforward use cases correctly.

How to reproduce

Repeat the actions in the GIF with this sand box https://codesandbox.io/s/react-storage-hooks-syincing-problem-7dgz5

react-storage-hooks-syincing-problem

ENV:

windows 1902 chrome 91 react 17

oscar-broman commented 2 years ago

You need to put a unique key, otherwise they will be stored as the same key.

PabloLION commented 2 years ago

Sorry that I didn't write the Expected behavior very clearly.

I expected when I change the first component (hooked to localStorage), the second one should also sync.

PabloLION commented 2 years ago

By the way I'm using https://usehooks-ts.com/react-hook/use-local-storage already. So if you are not maintaining it actively, I don't think we need to update this anymore. In this case, please consider close this issue.

ColeStansbury commented 1 year ago

+1 on this issue. I was tempted to switch to use-hooks-ts as well but I liked how this lib is smaller and that it has a reducer feature which use-hooks does not.

My work around (inspired by use-hooks lib) looks like this:


const MY_STORAGE_KEY = 'my-key';
export const useMyState = () => {
  const [state, setState, writeError] = useStorageState(localStorage, MY_STORAGE_KEY, 'my-default');

  useEffect(() => {
    window.dispatchEvent(new CustomEvent(MY_STORAGE_KEY, { detail: state }));
  }, [state]);

  window.addEventListener(MY_STORAGE_KEY, (event: CustomEvent) => {
    if (event.detail !== state) {
      setState(event.detail);
    }
  });
  return [state, setState, writeError];
};

I feel like this is a pretty easy fix on the lib though. In the mean time, you can also abstract this approach and use it for all of your useStorageState usages...