Skip to content

Instantly share code, notes, and snippets.

@ynifamily3
Last active July 28, 2021 00:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ynifamily3/dbd9376fee15a7de52a15d3141b1d3b2 to your computer and use it in GitHub Desktop.
Save ynifamily3/dbd9376fee15a7de52a15d3141b1d3b2 to your computer and use it in GitHub Desktop.
import localItemContext, {
setLocalItemValue,
} from "#/context/localItemContext";
import { useReactiveVar } from "@apollo/client";
import { useCallback, useEffect } from "react";
type UseReactiveLocalItemReturnType = <V>(
key: string,
defaultValue?: V,
) => [V, (value: V | ((prevState: V) => V) | null) => void];
const rawGetLocalItem = <T>(key: string) => {
const raw = localStorage.getItem(key);
const value =
raw !== null && raw !== undefined ? (JSON.parse(raw) as T) : null;
return value;
};
const useReactiveLocalItem: UseReactiveLocalItemReturnType = <T>(
key: string,
defaultValue?: T,
) => {
const localItem = useReactiveVar(localItemContext);
const raw = localItem[key];
const value =
raw !== null && raw !== undefined ? (JSON.parse(raw) as T) : defaultValue;
const setValue = useCallback(
(valueOrSetterFunction: T | ((prevState: T) => T) | null) => {
try {
if (typeof valueOrSetterFunction === "function") {
const setterFn = valueOrSetterFunction as (state: T) => T;
const newValue = setterFn(rawGetLocalItem(key) as T);
if (newValue === null) {
localStorage.removeItem(key);
} else {
localStorage.setItem(key, JSON.stringify(newValue));
setLocalItemValue(key, JSON.stringify(newValue));
}
return;
}
if (valueOrSetterFunction === null) {
localStorage.removeItem(key);
} else {
localStorage.setItem(key, JSON.stringify(valueOrSetterFunction));
}
setLocalItemValue(key, JSON.stringify(valueOrSetterFunction));
} catch (e) {
console.error(
"setValue LocalStorage Exception:",
e,
key,
valueOrSetterFunction,
);
}
},
[key],
);
if (value === undefined) {
throw new Error(
"[reacviteLocalItem] 로컬스토리지 값이 잘못되었습니다. (아니라면 기본값을 제공해 주세요)",
);
}
if ((raw === null || raw === undefined) && defaultValue !== undefined) {
setValue(defaultValue);
}
// 외부 브라우저의 localStorage 변경사항 수신
useEffect(() => {
const handler = () => {
const raw = localStorage.getItem(key);
const value =
raw !== null && raw !== undefined
? (JSON.parse(raw) as T)
: defaultValue;
if (value === undefined) {
throw new Error(
"[reacviteLocalItem] 로컬스토리지 값이 잘못되었습니다. (아니라면 기본값을 제공해 주세요)",
);
}
if ((raw === null || raw === undefined) && defaultValue !== undefined) {
setLocalItemValue(key, JSON.stringify(defaultValue));
} else {
setLocalItemValue(key, JSON.stringify(value));
}
};
window.addEventListener("storage", handler);
return () => {
window.removeEventListener("storage", handler);
};
}, [key, defaultValue]);
return [value, setValue];
};
export { useReactiveLocalItem };
@ynifamily3
Copy link
Author

ref로 잡아두기

@ynifamily3
Copy link
Author

차라리 현 상태를 localStorage에서 그냥 raw하게 긁어와서

해결하든지 해야지

어휴

@ynifamily3
Copy link
Author

해결함

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment