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.
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.
+1
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]);
...