Skip to content

Instantly share code, notes, and snippets.

@amille44420
Created October 26, 2023 04:04
Show Gist options
  • Save amille44420/261447169c06f4a25c9ad6815de9def6 to your computer and use it in GitHub Desktop.
Save amille44420/261447169c06f4a25c9ad6815de9def6 to your computer and use it in GitHub Desktop.
import PubSub from 'pubsub-js';
import { useSyncExternalStore, useCallback, useEffect, useRef } from 'react';
const store: Record<string, any> = {};
const useMemoryStorage = <Value = any>(key: string, defaultValue?: Value) => {
const subscribe = useCallback(
(onStoreChange: () => void) => {
const token = PubSub.subscribe(`appvantage.memoryStorage.${key}`, onStoreChange);
return () => {
PubSub.unsubscribe(token);
};
},
[key]
);
const getSnapshot = useCallback(() => store[key] as Value, [key]);
const value = useSyncExternalStore(subscribe, getSnapshot);
const setValue = useCallback(
(nextValue: Value) => {
// update store value
store[key] = nextValue;
// then publish the change
PubSub.publish(`appvantage.memoryStorage.${key}`);
},
[key]
);
const isInitializedFor = useRef<string | null>(null);
const shouldInitialize = isInitializedFor.current !== key;
const shouldSetValue = shouldInitialize && value === undefined && defaultValue !== undefined;
useEffect(() => {
if (shouldInitialize) {
// ensure to set the latest key
isInitializedFor.current = key;
if (shouldSetValue) {
// we can set the default value instead
setValue(defaultValue);
}
}
}, [key, defaultValue, shouldSetValue, shouldInitialize, isInitializedFor, setValue]);
const currentValue = shouldSetValue ? defaultValue : value;
return [currentValue, setValue];
};
export default useMemoryStorage;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment