rehooks / local-storage

React hook which syncs localStorage[key] with the comp.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Invariant: "Hooks can only be called inside the body of a function component."

colshacol opened this issue · comments

Doesn't seem like I am doing anything wrong. 🤷‍♂️ I just set it up with 16.7.0-alpha.0 and followed the example.

inv

https://codesandbox.io/s/n7wj20np04

I also ran into this issue. I was able to just copy the source code into my project and it worked. Wonder if it a packing issue.

Checking this out, it looks strange though.

The coolest thing about this plugin is also the biggest bummer. The local storage events only fire when the browser tab is not active. Nothing you can do about that but just thought I might share it before others get as excited as I was.

@nmaves Didn't know this. I never used localStorage sync for single tab though, always used it for multiple tabs. Nice to know this.

I created a package a few months ago to fire events for localStorage/sessionStorage in the same tab that they originate from, as they're happening.

https://www.npmjs.com/package/storage-changed

Basically...

import storageChanged from 'storage-changed'

storageChanged('local')
storageChanged('session')

window.addEventListener('localStorageChanged', (event) => {
  console.log('local changed:', event.detail.name, event.detail.value)
})

window.addEventListener('sessionStorageChanged', (event) => {
  console.log('session changed:', event.detail.name, event.detail.value)
})

localStorage.setItem('foo', 'bar')
// local changed: foo bar

sessionStorage.setItem('baz', 'bah')
// session changed: baz bah

For those who aren't bothered about cross tab changes and just want to share a change in local storage using hooks:

export function useLocalStorage(key) {
  const [storageValue, updateStorageValue] = useState(window.localStorage[key]);

  function onChange({ detail }) {
    if (detail.key === key) updateStorageValue(detail.value);
  }

  useEffect(() => {
    window.addEventListener('onLocalStorageChange', onChange);
    return () => window.removeEventListener('onLocalStorageChange', onChange);
  });

  return [
    storageValue,
    (value) => {
      window.localStorage.setItem(key, value);

      window.dispatchEvent(new CustomEvent('onLocalStorageChange', {
        detail: { key, value },
      }));
    },
  ];
}
const [theme, updateTheme] = useLocalStorage('theme');

You may want to modify to set the storage value if it's not available, e.g.

export function useLocalStorage(key, initialValue) {
  if (!window.localStorage[key]) window.localStorage.setItem(key, initialValue);
  const [storageValue, updateStorageValue] = useState(window.localStorage[key]);
  ...