Skip to content

Commit 7f98f53

Browse files
committed
Add useLocalStorage to main package
1 parent 0b307fa commit 7f98f53

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

index.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,72 @@ export function useList(defaultList = []) {
564564
return [list, { set, push, removeAt, insertAt, updateAt, clear }];
565565
}
566566

567+
const dispatchStorageEvent = (key, newValue) => {
568+
window.dispatchEvent(new StorageEvent("storage", { key, newValue }));
569+
};
570+
571+
const setLocalStorageItem = (key, value) => {
572+
const stringifiedValue = JSON.stringify(value);
573+
window.localStorage.setItem(key, stringifiedValue);
574+
dispatchStorageEvent(key, stringifiedValue);
575+
};
576+
577+
const removeLocalStorageItem = (key) => {
578+
window.localStorage.removeItem(key);
579+
dispatchStorageEvent(key, null);
580+
};
581+
582+
const getLocalStorageItem = (key) => {
583+
return window.localStorage.getItem(key);
584+
};
585+
586+
const useLocalStorageSubscribe = (callback) => {
587+
window.addEventListener("storage", callback);
588+
return () => window.removeEventListener("storage", callback);
589+
};
590+
591+
const getLocalStorageServerSnapshot = () => {
592+
throw Error("useLocalStorage is a client-only hook");
593+
};
594+
595+
export function useLocalStorage(key, initialValue) {
596+
const getSnapshot = () => getLocalStorageItem(key);
597+
598+
const store = React.useSyncExternalStore(
599+
useLocalStorageSubscribe,
600+
getSnapshot,
601+
getLocalStorageServerSnapshot
602+
);
603+
604+
const setState = React.useCallback(
605+
(v) => {
606+
try {
607+
const nextState = typeof v === "function" ? v(JSON.parse(store)) : v;
608+
609+
if (nextState === undefined || nextState === null) {
610+
removeLocalStorageItem(key);
611+
} else {
612+
setLocalStorageItem(key, nextState);
613+
}
614+
} catch (e) {
615+
console.warn(e);
616+
}
617+
},
618+
[key, store]
619+
);
620+
621+
React.useEffect(() => {
622+
if (
623+
getLocalStorageItem(key) === null &&
624+
typeof initialValue !== "undefined"
625+
) {
626+
setLocalStorageItem(key, initialValue);
627+
}
628+
}, [key, initialValue]);
629+
630+
return [store ? JSON.parse(store) : initialValue, setState];
631+
}
632+
567633
export function useLockBodyScroll() {
568634
React.useEffect(() => {
569635
const originalStyle = window.getComputedStyle(document.body).overflow;

0 commit comments

Comments
 (0)