๋๋ ๋ณดํต react ํ๋ก์ ํธ๋ฅผ ํ๊ฒ ๋๋ฉด ๊ฐ๋จํ ์ํ ๊ด๋ฆฌ๋ค์ ๋๋ถ๋ถ recoil์ ํตํด ํ๋๋ฐ
์ด๋ฒ์ recoil์ ๋ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ๋ค์ ๋ํด ๋ ์์น๋ฅผ ํ๋ค๊ฐ Atom Effects์ ๋ํด ์์๋ณด๊ฒ ๋์๋ค.
Recoil ๊ณต์ ํ์ด์ง์ Atom Effects ์ค๋ช ์ ์๋ ๋งํฌ๋ฅผ ํตํด ์ฐธ๊ณ ํ๋ฉด ๋๋ค.
recoil ๊ณต์ ํ์ด์ง์์ ์๊ฐํ๋ atom effects๋ ๋ถ์ํจ๊ณผ๋ค์ ๊ด๋ฆฌํ๊ณ Recoil์ atom์ ์ด๊ธฐํํ๊ฑฐ๋ ๋๊ธฐํํ๊ธฐ ์ํด ์ฌ์ฉํ๋ API๋ผ๊ณ ์ค๋ช ํ๋ค.
Atom Effects
- ์ํ ์ง์์ฑ
- ์ํ ๋๊ธฐํ
- ํ์คํ ๋ฆฌ ๊ด๋ฆฌ
- ๋ก๊น
๋ฑ์ ์ ์ฉํ๊ณ React Effects์๋ ์ ์ฌํ์ง๋ง Atom Effects๋ atom์ ์ ์ํ ๋ atom ์ ์์ ์ผ๋ถ๋ก ์ ์ ๋๋ค๊ณ ํ๋ค.
์ฆ effects์ atom ์ ์๋ฅผ ํจ๊ป ๋ฐฐ์นํ๊ฒ ํ๋ ๋๊ธฐํ ํจ๊ณผ๋ผ๊ณ ๋ณผ ์ ์๊ฒ ๋ค.
Atom Effects๋ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ๋ฆฌ์กํธ์ useEffect()๋ก ๋์ฒด๋ ์ ์์ผ๋ atom์ ์งํฉ์ ๋ฆฌ์กํธ ์ปจํ ์คํธ์ ์ธ๋ถ์์ ์์ฑ๋๋ฉฐ, ํนํ ๋์ ์ผ๋ก ์์ฑ๋ atom์ ๊ฒฝ์ฐ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ ๋ด์์ ํจ๊ณผ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ด๋ ค์ธ ์ ์๊ณ ์ฒ์์ atom ๊ฐ์ ์ด๊ธฐํํ๊ฑฐ๋ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง(SSR)๊ณผ ํจ๊ป ์ฌ์ฉ๋ ์๋ ์์ด์ atom effects๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ผ๊ณ ์๋ดํ๋ค.
Atom Effects ์ ์
type AtomEffect<T> = ({
node: RecoilState<T>, // A reference to the atom itself
storeID: StoreID, // ID for the <RecoilRoot> or Snapshot store associated with this effect.
trigger: 'get' | 'set', // The action which triggered initialization of the atom
// Callbacks to set or reset the value of the atom.
// This can be called from the atom effect function directly to initialize the
// initial value of the atom, or asynchronously called later to change it.
setSelf: (
| T
| DefaultValue
| Promise<T | DefaultValue> // Only allowed for initialization at this time
| ((T | DefaultValue) => T | DefaultValue),
) => void,
resetSelf: () => void,
// Subscribe to changes in the atom value.
// The callback is not called due to changes from this effect's own setSelf().
onSet: (
(newValue: T, oldValue: T | DefaultValue, isReset: boolean) => void,
) => void,
// Callbacks to read other atoms/selectors
getPromise: <S>(RecoilValue<S>) => Promise<S>,
getLoadable: <S>(RecoilValue<S>) => Loadable<S>,
getInfo_UNSTABLE: <S>(RecoilValue<S>) => RecoilValueInfo<S>,
}) => void | () => void; // Optionally return a cleanup handler
Atom Effects๋ effects ์ต์ ์ ํตํด atoms์ ์ฐ๊ฒฐ๋์ด ์๊ณ ๊ฐ๊ฐ์ atom์ ์ด๊ธฐํ๋ ๋ ์ฐ์ ์์์ ๋ฐ๋ผ ํธ์ถ๋๋ atom effect ํจ์๋ค์ ๋ฐฐ์ด์ ์ฐธ์กฐํ ์ ์๋ค๊ณ ํ๋ค.
atom effects์ ์ด๊ธฐํ๋ฅผ ์ํ cleanup ํธ๋ค๋ฌ๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
๋ด๊ฐ ํ๊ณ ์ถ์๋ atom effects์ ๊ธฐ๋ฅ์ ๋ก์ปฌ ์คํ ๋ฆฌ์ง ์ง์์ฑ ํํธ์๋๋ฐ, ์๋์ ๊ฐ์ ์ค๋ช ์ด ์ ํ์์๋ค.
Atom Effects๋ atom ์ํ๋ฅผ ๋ธ๋ผ์ฐ์ ๋ก์ปฌ ์คํ ๋ฆฌ์ง์์ ์ ์งํ๊ธฐ ์ํด์ ์ฌ์ฉ๋ ์ ์์ต๋๋ค. localStorage ๋ ๋๊ธฐ์์ด๋ฏ๋ก ๋ฐ์ดํฐ๋ฅผ async/await ํน์ Promise ์์ด ์ง์ ๋ฐ์์ฌ ์ ์์ต๋๋ค.
์๋๋ Atom Effects๋ฅผ ์ด์ฉํ์ฌ localStorage์ ๋๊ธฐํ ๋ฐ ์ด๊ธฐํ ์์ ์ ํด์ฃผ๋ ์ฝ๋์ด๋ค.
const localStorageEffect = key => ({setSelf, onSet}) => {
const savedValue = localStorage.getItem(key)
if (savedValue != null) {
setSelf(JSON.parse(savedValue));
}
onSet((newValue, _, isReset) => {
isReset
? localStorage.removeItem(key)
: localStorage.setItem(key, JSON.stringify(newValue));
});
};
const currentUserIDState = atom({
key: 'CurrentUserID',
default: 1,
effects: [
localStorageEffect('current_user'),
]
});
์ด๋ฐ ์์ผ๋ก ๋ก์ปฌ ์คํ ๋ฆฌ์ง ์ดํํธ๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํ ์ ์๋ค.
์ค์ ๋ก refreshToken์ ์ป์ด์ atom์ setRecoilValue๋ฅผ ํตํด token์ ์ ์ฅํ๋ ์๋์ผ๋ก localStorageEffect ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉฐ ์ ์์ ์ผ๋ก ๋ก์ปฌ ์คํ ๋ฆฌ์ง์ ์ ์ฅ๋๋ ๊ฒ์ ํ์ธํ๋ค!
Recoil์ ๋ค๋ฅธ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ๋นํด ๊ฐ๋ณ๊ณ ์ํ ๊ด๋ฆฌ๋ฅผ ์ํ ์ต์ํ์ ๊ธฐ๋ฅ๋ค๋ง ์ ๊ณตํ๋ค๊ณ ์๊ฐํ์๋๋ฐ ๋ถ๊ฐ ๊ธฐ๋ฅ๋ค์ ๊ผผ๊ผผํ ๋ณด์ง ์์ ๋์ ๋ฌด์งํ ํ๋จ์ด์๋ค.ใ ใ ์ญ์ ๊ฐ๋ณ๊ฒ ํ์ด๋ณด๊ณ ํ๋จํ๋ฉด ์ ๋๋ค๋ ๊ฒ์ ๋ ํ ๋ฒ ๋๊ผ๋ค.