Files
outline/app/hooks/usePersistedState.ts
Tom Moor e4e98286f4 fix: Embed disabled state should persist (#3407)
* Normalize code around localStorage
Persist disabled embed state

* fix: Cannot view more than 10 starred items on load

* More tidying of sidebar state
2022-04-17 10:24:40 -07:00

52 lines
1.5 KiB
TypeScript

import * as React from "react";
import { Primitive } from "utility-types";
import Storage from "~/utils/Storage";
/**
* A hook with the same API as `useState` that persists its value locally and
* syncs the value between browser tabs.
*
* @param key Key to store value under
* @param defaultValue An optional default value if no key exists
* @returns Tuple of the current value and a function to update it
*/
export default function usePersistedState(
key: string,
defaultValue: Primitive
) {
const [storedValue, setStoredValue] = React.useState(() => {
if (typeof window === "undefined") {
return defaultValue;
}
return Storage.get(key) ?? defaultValue;
});
const setValue = (value: Primitive | ((value: Primitive) => void)) => {
try {
// Allow value to be a function so we have same API as useState
const valueToStore =
value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
Storage.set(key, valueToStore);
} catch (error) {
// A more advanced implementation would handle the error case
console.log(error);
}
};
// Listen to the key changing in other tabs so we can keep UI in sync
React.useEffect(() => {
const updateValue = (event: any) => {
if (event.key === key && event.newValue) {
setStoredValue(JSON.parse(event.newValue));
}
};
window.addEventListener("storage", updateValue);
return () => window.removeEventListener("storage", updateValue);
}, [key]);
return [storedValue, setValue];
}