๐ช store
Jotai
์์ ์ฌ์ฉํ๋ย Store
๋ย createStore
ํจ์๋ฅผ ํตํด ์์ฑ๋ฉ๋๋ค.
createStore
๋ย 700
์ค์ด ๋๊ธฐ ๋๋ฌธ์, ์ ์ฒด ๊ตฌํ ์ฝ๋๋ ์๋ตํ๊ฒ ์ต๋๋ค.
์ธํฐํ์ด์ค๋ฅผ ์ํด ๋ฐํ๊ฐ๋ง ์ดํด๋ณด๋ฉด ์๋์ ๊ฐ์ต๋๋ค.
return {
get: readAtom,
set: writeAtom,
sub: subscribeAtom,
};
return {
get: readAtom,
set: writeAtom,
sub: subscribeAtom,
};
๊ฐ๊ฐ์ ๋ํด ์ดํด๋ณด๋ฉด,ย get
์ ๊ฒฝ์ฐย store
์ ์กด์ฌํ๋ย atom
์ ๊ฐ์ ์ฝ์ ๋ ์ฌ์ฉ๋๋ฉฐ,ย set
์ ๊ฒฝ์ฐย store
์ ๊ฐ์ ์ธ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
sub
์ ๊ฒฝ์ฐ,ย atom
๊ณผlistener
๋ฅผ ๋งค๊ฒ๋ณ์๋ก ๋ฐ์ย listeners
ย set
์ ์ ์ฅํฉ๋๋ค.
jotai
์ ๋ชจ๋ ๋์์ย store
์ย get
,ย set
,ย sub
ย ๋ฉ์๋๋ฅผ ํตํด ์ด๋ฃจ์ด์ง๊ฒ ๋ฉ๋๋ค.
atom
์ ๊ฐ์ ์
๋ฐ์ดํธ ํ ๋ ์ฌ์ฉ๋๋ย useSetAtom
ย ํ
์์๋ย set
ย ๋ฉ์๋๋ฅผ ์ด์ฉํฉ๋๋ค.
export function useSetAtom<Value, Args extends any[], Result>(
atom: WritableAtom<Value, Args, Result>,
options?: Options
) {
const store = useStore(options)
const setAtom = useCallback(
(...args: Args) => {
...
return store.set(atom, ...args)
},
[store, atom]
)
return setAtom
}
export function useSetAtom<Value, Args extends any[], Result>(
atom: WritableAtom<Value, Args, Result>,
options?: Options
) {
const store = useStore(options)
const setAtom = useCallback(
(...args: Args) => {
...
return store.set(atom, ...args)
},
[store, atom]
)
return setAtom
}
atom
์ ๊ฐ์ ์ฝ์ ๋ ์ฌ์ฉ๋๋ย useAtomValue
ย ํ
์์๋ย get
,ย subscribe
ย ๋ฉ์๋๋ฅผ ์ด์ฉํฉ๋๋ค.
export function useAtomValue<Value>(atom: Atom<Value>, options?: Options) {
const store = useStore(options);
const [[valueFromReducer, storeFromReducer, atomFromReducer], rerender] =
useReducer<
ReducerWithoutAction<readonly [Value, Store, typeof atom]>,
undefined
>(
(prev) => {
const nextValue = store.get(atom);
if (
Object.is(prev[0], nextValue) &&
prev[1] === store &&
prev[2] === atom
) {
return prev;
}
return [nextValue, store, atom];
},
undefined,
() => [store.get(atom), store, atom]
);
let value = valueFromReducer;
if (storeFromReducer !== store || atomFromReducer !== atom) {
rerender();
value = store.get(atom);
}
const delay = options?.delayuseEffect(() => {
const unsub = store.sub(atom, () => {
if (typeof delay === "number") {
// delay rerendering to wait a promise possibly to resolve
setTimeout(rerender, delay);
return;
}
rerender();
});
rerender();
return unsub;
}, [store, atom, delay]);
return isPromiseLike(value) ? use(value) : (value as Awaited<Value>);
}
export function useAtomValue<Value>(atom: Atom<Value>, options?: Options) {
const store = useStore(options);
const [[valueFromReducer, storeFromReducer, atomFromReducer], rerender] =
useReducer<
ReducerWithoutAction<readonly [Value, Store, typeof atom]>,
undefined
>(
(prev) => {
const nextValue = store.get(atom);
if (
Object.is(prev[0], nextValue) &&
prev[1] === store &&
prev[2] === atom
) {
return prev;
}
return [nextValue, store, atom];
},
undefined,
() => [store.get(atom), store, atom]
);
let value = valueFromReducer;
if (storeFromReducer !== store || atomFromReducer !== atom) {
rerender();
value = store.get(atom);
}
const delay = options?.delayuseEffect(() => {
const unsub = store.sub(atom, () => {
if (typeof delay === "number") {
// delay rerendering to wait a promise possibly to resolve
setTimeout(rerender, delay);
return;
}
rerender();
});
rerender();
return unsub;
}, [store, atom, delay]);
return isPromiseLike(value) ? use(value) : (value as Awaited<Value>);
}
reducer
ย ๋ด๋ถ ๋ก์ง์ ํตํด ๋งคย rendering
ย ์์ ,ย store.get(atom)
์ ํตํดย store
์์ ํด๋น atom์
ย value
๋ฅผ ์ฝ์ด์ค๋ฉฐ, ํด๋น ๊ฐ์ ์ํ๋ก ์ฌ์ฉํด, ์ปดํฌ๋ํธ์ ์ ๋ฌํ๊ณ ์์ต๋๋ค.
const [[valueFromReducer, storeFromReducer, atomFromReducer], rerender] =
useReducer<
ReducerWithoutAction<readonly [Value, Store, typeof atom]>,
undefined
>(
(prev) => {
const nextValue = store.get(atom);
if (
Object.is(prev[0], nextValue) &&
prev[1] === store &&
prev[2] === atom
) {
return prev;
}
return [nextValue, store, atom];
},
undefined,
() => [store.get(atom), store, atom]
);
let value = valueFromReducer;
return isPromiseLike(value) ? use(value) : (value as Awaited<Value>);
const [[valueFromReducer, storeFromReducer, atomFromReducer], rerender] =
useReducer<
ReducerWithoutAction<readonly [Value, Store, typeof atom]>,
undefined
>(
(prev) => {
const nextValue = store.get(atom);
if (
Object.is(prev[0], nextValue) &&
prev[1] === store &&
prev[2] === atom
) {
return prev;
}
return [nextValue, store, atom];
},
undefined,
() => [store.get(atom), store, atom]
);
let value = valueFromReducer;
return isPromiseLike(value) ? use(value) : (value as Awaited<Value>);
์ปดํฌ๋ํธ๊ฐย mount
ย ๋ ์ดํ,ย useEffect
ย ํ
์ ํตํด,ย store
๋ฅผ ๊ตฌ๋
ํ๋ ๊ฒ๋ ํ์ธํ ์ ์์ต๋๋ค.
useEffect(() => {
const unsub = store.sub(atom, () => {
// ...rerender()
});
rerender();
return unsub;
}, [store, atom, delay]);
useEffect(() => {
const unsub = store.sub(atom, () => {
// ...rerender()
});
rerender();
return unsub;
}, [store, atom, delay]);
์ด๋, ์ธ์๋กย rerender
ย ํจ์๋ฅผ ์ ๋ฌํด,ย store
์์ ๋ณํ๊ฐ ๋ฐ์ํ๋ฉด, ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌ๋ ๋๋ง ํ๊ฒ ๋ฉ๋๋ค.
์ข ๋ ํ์คํ๊ฒ ์ดํด๋ณด๊ธฐ ์ํด,
subscribeAtom
ย ๋ฉ์๋์ย listener
๋ฅผ ์คํํ๋ ๋ถ๋ถ์ ์ดํด๋ณด๋ฉด ์๋์ ๊ฐ์ต๋๋ค.
const subscribeAtom = (atom: AnyAtom, listener: () => void) => {
const mounted = addAtom(atom);
const flushed = flushPending();
const listeners = mounted.l;
listeners.add(listener);
// ...
return () => {
listeners.delete(listener);
delAtom(atom);
// ...
};
};
const flushPending = (): void | Set<AnyAtom> => {
// ...
mounted.l.forEach((listener) => listener());
// ...
};
const subscribeAtom = (atom: AnyAtom, listener: () => void) => {
const mounted = addAtom(atom);
const flushed = flushPending();
const listeners = mounted.l;
listeners.add(listener);
// ...
return () => {
listeners.delete(listener);
delAtom(atom);
// ...
};
};
const flushPending = (): void | Set<AnyAtom> => {
// ...
mounted.l.forEach((listener) => listener());
// ...
};
subscribeAtom
ย ๋ฉ์๋๋ฅผ ํตํดย listener
๋ฅผ ์ ์ฅํ๊ณ ,ย atom
์ ๊ฐ์ด ๋ณ๊ฒฝ ๋ ๋ ๋ง๋ค ์คํ๋๋ย flushPending
ย ๋ฉ์๋์์ ํด๋นย listener
๋ฅผ ์คํํฉ๋๋ค.
๊ทธ๋ฆผ์ผ๋ก ์์๋ฅผ ๋ํ๋ด๋ฉด ์๋์ ๊ฐ์ต๋๋ค.
- Component Mount
- useEffect Execute and Subscribe Store(store.subscribeAtom)
- atom change in store
- publish and rerender called
๋ค์ ๋ด์ฉ์ ์ดํด๋ณด๊ธฐ์ ์, ์ง๊ธ๊น์ง ์ดํด๋ณธย Component
,ย Store
,ย Provider
,ย Atom
์ ๊ด๊ณ๋ฅผ ์ดํด๋ณด๋ฉด ์๋ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ต๋๋ค.
- ๊ฐ๊ฐ์ย
atom
์ ํ๋์ยstore
์ ์ํ๋ค. Provider
๋ยStore
๋ฅผ ๊ฐ๋ฆฌํค๋ ๊ป๋ฐ๊ธฐ์ด๋ฉฐ ๊ฐ๊ฐ์ยSubtree
์ ๋ ๋ฆฝ์ ์ธยStore
๋ฅผ ๊ฐ๋๋ก ๋ง๋ค์ด์ค๋ค.- ์ปดํฌ๋ํธ์ย
Store
๋ฅผยPub-Sub
ย ๊ด๊ณ์ด๋ฉฐ,ยStore
๊ฐ ์ ๋ฐ์ดํธ๋๋ฉดยSubscribe
๋ฅผ ํตํด ๋ฆฌ๋ ๋๋ง ๋๋ค.
๐ง ์์ฑํ Atom์ ์ธ์ Store์ ๋ค์ด๊ฐ๊น?
๋ค์์ผ๋ก,ย atom
ย ํจ์๋ฅผ ์ด์ฉํด ๋ง๋ ย atom config
๊ฐ ์ธ์ ย store
์ ๋ค์ด๊ฐ๋์ง๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๊ฒฐ๋ก ๋ถํฐ ๋งํ์๋ฉด,ย atom
์ ํด๋นย atom
์ดย Store
์์ ์ฒ์ ์ฌ์ฉ๋๋ ์์ ์ย Store
์ ๋ค์ด๊ฐ๊ฒ ๋ฉ๋๋ค.
์กฐ๊ธ ๋ ์์ธํ ์ค๋ช
ํ์๋ฉด, ํด๋นย atom
์ดย Store
์ ํน์ ๋ฉ์๋์ ๋งค๊ฒ๋ณ์๋ก ํธ์ถ๋๋ ์์ ์ ๋ค์ด๊ฐ๊ฒ ๋ฉ๋๋ค.
Store
๋ด๋ถ์์ย Atom
์ ๋ค์๊ณผ ๊ฐ์ย WeakMap
์ ํตํด ๊ด๋ฆฌ๋ฉ๋๋ค.
const atomStateMap = new WeakMap<AnyAtom, AtomState>();
const atomStateMap = new WeakMap<AnyAtom, AtomState>();
ํด๋นย WeakMap
์ดย Set
๋๋ ์์ ์ย setAtomState
๊ฐ ํธ์ถ๋๋ ์์ ๋ฐ์ ์์ต๋๋ค.
const setAtomState = <Value>(
atom: Atom<Value>,
atomState: AtomState<Value>
): void => {
...
const prevAtomState = atomStateMap.get(atom)
atomStateMap.set(atom, atomState)
...
}
const setAtomState = <Value>(
atom: Atom<Value>,
atomState: AtomState<Value>
): void => {
...
const prevAtomState = atomStateMap.get(atom)
atomStateMap.set(atom, atomState)
...
}
setAtomState
๊ฐ ํธ์ถ๋๋ ์์ ์ ์ญ์ถ์ ํ ๊ฒฐ๊ณผ ์๋์ ๊ฐ์ ํธ์ถ ์ฒด์ด๋์ ํ์ธ ํ ์ ์์์ต๋๋ค.
1๏ธ. readAtomCalled when store.get(atom) called
const readAtom = <Value>(atom: Atom<Value>): Value => returnAtomValue(readAtomState(atom))
2๏ธ. readAtomState called
3๏ธ. setAtomValueOrPromise called
4๏ธ. setAtomValue called
5๏ธ. setAtomState called
6๏ธ. atomStateWeakMap.set(atom) called
Store
ย ๋ด๋ถ ๋ฉ์๋๋ค์ ํธ์ถ์์๋ฅผ ์ญ์ถ์ ํด๋ณธ ๊ฒฐ๊ณผ,ย store
์ ์กด์ฌํ๋ย atom
์ ์ฝ์ ๋ (when store.get(atom) called
), ํด๋นย atom
์ดย store
์ ์กด์ฌํ์ง ์๋๋ค๋ฉด ํด๋นย atom
์ย store
์ ๋ฃ๋ ๊ฒ์ ํ์ธํ ์ ์์์ต๋๋ค.
๋ฐ๋ผ์, ์๋์ ๊ฐ์ด ์ปดํฌ๋ํธ ๋ฐ๊นฅ์์ย Store
๋ฅผ ํตํดย atom
์ ์ ๊ทผํด ๊ฐ์ ํ์ธํด๋ณด๋ฉดย Hook
ย ํธ์ถ ์ด์ ์๋,ย store
์ย atom
์ด ๋ค์ด๊ฐ ์์ผ๋ฉฐ, ํด๋น ๊ฐ์ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
const counterAtom = atom(1);
const doubleCountAtom = atom((get) => {
return get(counterAtom) * 2;
});
const store = getDefaultStore();
console.log("store.get(counterAtom) : ", store.get(counterAtom)); // 1 ์ถ๋ ฅ
console.log("store.get(doubleCountAtom) : ", store.get(doubleCountAtom)); // 2 ์ถ๋ ฅ
function App() {
const [count, setCount] = useAtom(counterAtom);
const doubleCount = useAtomValue(doubleCountAtom);
return (
<div className="App">
<div>
<button onClick={() => setCount((prev) => prev - 1)}>-</button>
<span>{count}</span>
<button onClick={() => setCount((prev) => prev + 1)}>+</button>
</div>
<div>
<span>double Count Atom : {doubleCount}</span>
</div>
</div>
);
}
const counterAtom = atom(1);
const doubleCountAtom = atom((get) => {
return get(counterAtom) * 2;
});
const store = getDefaultStore();
console.log("store.get(counterAtom) : ", store.get(counterAtom)); // 1 ์ถ๋ ฅ
console.log("store.get(doubleCountAtom) : ", store.get(doubleCountAtom)); // 2 ์ถ๋ ฅ
function App() {
const [count, setCount] = useAtom(counterAtom);
const doubleCount = useAtomValue(doubleCountAtom);
return (
<div className="App">
<div>
<button onClick={() => setCount((prev) => prev - 1)}>-</button>
<span>{count}</span>
<button onClick={() => setCount((prev) => prev + 1)}>+</button>
</div>
<div>
<span>double Count Atom : {doubleCount}</span>
</div>
</div>
);
}
๐ ๏ธย Atom์ Dependency๋ ์ด๋ป๊ฒ ๊ด๋ฆฌํ ๊น?
๋จผ์ ,ย ๊ณต์๋ฌธ์๋ฅผ ํตํด ์ดํด๋ณด๊ฒ ์ต๋๋ค.
To keep track of all the dependents, we need to add one more property to the atom's state.
Dependency๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด, ์๋์ ๊ฐ์ดย dependents
๋ผ๋ย property
๋ฅผ ์ฌ์ฉํฉ๋๋ค.
const atomState = {
value: atom.init,
listeners: new Set(),
dependents: new Set(),
};
const atomState = {
value: atom.init,
listeners: new Set(),
dependents: new Set(),
};
ํด๋นย dependents
ย ๋ผ๋ย property
๋ฅผ ํตํด ํด๋นย atom
์ ์์กด์ ์ธย atom
์ ๊ด๋ฆฌํฉ๋๋ค.
์๋ฅผ ๋ค์ด, ์๋์ ๊ฐ์ดย atom X
๊ฐย atom Y
์ ์์กดํ๋ ๊ฒฝ์ฐ๋ผ๋ฉด,ย atom Y
์ย dependents
ย property
์๋ย atom X
๊ฐ ๋ค์ด๊ฐ ์์ ๊ฒ์
๋๋ค.
const atomX = atom(1);
const atomY = atom((get) => get(atomX) + 1);
const atomX = atom(1);
const atomY = atom((get) => get(atomX) + 1);
1ํธ์์ย atom
์ ์ดํด๋ณผ ๋,ย atom
์ ๊ฐ์ ์ฝ์๋๋ย atom
ย ๋ด๋ถ์์ย read
๋ผ๋ย property
๋ฅผ ํตํดย store
์ ์กด์ฌํ๋ย atom
์ย value
๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์ ํ์ธํ ์ ์์์ต๋๋ค.
export function atom<Value, Args extends unknown[], Result>(
read: Value | Read<Value, SetAtom<Args, Result>>,
write?: Write<Args, Result>
) {
...
if (typeof read === 'function') {
config.read = read as Read<Value, SetAtom<Args, Result>>
} else {
...
config.read = (get) => get(config)
...
}
return config
}
export function atom<Value, Args extends unknown[], Result>(
read: Value | Read<Value, SetAtom<Args, Result>>,
write?: Write<Args, Result>
) {
...
if (typeof read === 'function') {
config.read = read as Read<Value, SetAtom<Args, Result>>
} else {
...
config.read = (get) => get(config)
...
}
return config
}
atom
์ ์ฒซ ๋ฒ์งธ ๋งค๊ฒ๋ณ์๋ก ๋ฐ๋ย read
์ ํ์
์ด ํจ์์ธ์ง,ย atom
ย config
์ธ์ง์ ๋ฐ๋ผ,ย atom
์ด ๋ฐํํ๋ย read
๊ฐ ๋ฌ๋ผ์ง๊ฒ ๋ฉ๋๋ค.
- read์ ํ์ ์ด ํจ์์ธ ๊ฒฝ์ฐ(๋ค๋ฅธ atom์ ์์กด์ ์ธ atom) : ๋งค๊ฒ๋ณ์๋ก ๋ฐ๋ read ๋ฐํ
- read์ ํ์ ์ด ํจ์๊ฐ ์๋ ๊ฒฝ์ฐ(๋ค๋ฅธ atom์ ์์กด์ ์ด์ง ์์ atom) : ์๊ธฐ ์์ (atom config)์ ๋งค๊ฒ๋ณ์๋ก ๋ฃ๋ ํจ์๋ฅผ ๋ฐํ
1ํธ์์ ์ดํด๋ณด์๋ฏ, ๋งคย rendering
ย ๋ง๋ค,ย atom
์ย read
๊ฐ ์คํ๋์ดย store
์์ ํด๋นย atom
์ ๊ฐ์ ์ฝ์ด์ค๊ฒ ๋ฉ๋๋ค.
๋ฐ๋ผ์, ๋ค์์ผ๋ก๋ย store
์์ ํด๋นย atom
์ ๊ฐ์ ์ฝ๋ ๋ถ๋ถ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
const readAtom = (atom) => {
const atomState = getAtomState(atom);
const get = (a) => {
if (a === atom) {
return atomState.value;
}
const aState = getAtomState(a);
aState.dependents.add(atom); // XXX add onlyreturn
readAtom(a); // XXX no caching
};
const value = atom.read(get);
atomState.value = value;
return value;
};
const readAtom = (atom) => {
const atomState = getAtomState(atom);
const get = (a) => {
if (a === atom) {
return atomState.value;
}
const aState = getAtomState(a);
aState.dependents.add(atom); // XXX add onlyreturn
readAtom(a); // XXX no caching
};
const value = atom.read(get);
atomState.value = value;
return value;
};
get
ํจ์๋ฅผ ์ดํด๋ณด๋ฉด ๋งค๊ฒ๋ณ์๋ก ๋ฐ๋ย a
๊ฐ ์๊ธฐ์์ ์ด๋ผ๋ฉด(์์ ์ดํด๋ณธ 2๋ฒ ์ผ์ด์ค โย if (a === atom)
) ํด๋นย atom
์ย value
๋ฅผ ๋ฐํํ๊ณ , ๋งค๊ฒ๋ณ์๋ก ๋ฐ๋ a๊ฐ ์๊ธฐ์์ ์ด ์๋ ๊ฒฝ์ฐ(์์ ์ดํด๋ณธ 1๋ฒ ์ผ์ด์ค), ๋งค๊ฒ๋ณ์๋ก ๋ฐ๋ย a
์ ๊ฐ์ย store
์์ ๊ฐ์ง๊ณ ์ค๊ฒ ๋ฉ๋๋ค(const aState = getAtomState(a)
).
๊ทธ ์ดํ, ํด๋นย atom
์ย dependents
ย property
์ย a
๋ฅผ ์ถ๊ฐํ๊ณ (aState.dependents.add(atom)
), ์ฌ๊ท์ ์ผ๋กย readAtom
์ ํธ์ถํด์ ๋ค๋ฅธย atom
์ ์์กด์ ์ธย atom
์ธ์ง ์ฌ๋ถ์ ๋ฐ๋ผย read
ย ๋ก์ง์ ์ํํ๊ฒ ๋ฉ๋๋ค.
atom
์ ๊ฐ์ด ๋ฐ๋ ๋๋,ย dependents
ย property
์ ์ ์ฅ๋์ด ์๋ ๋ชจ๋ ย atom
์๊ฒย notify
๋ฅผ ํ๊ฒ ๋๊ณ , ๊ฐ๊ฐ์ atom๋ค์ listener ํจ์๋ฅผ ์คํํ๊ฒ ๋ฉ๋๋ค.(์์์ ์ดํด๋ณธย rerender
)
const notify = (atom) => {
const atomState = getAtomState(atom);
atomState.dependents.forEach((d) => {
if (d !== atom) notify(d);
});
atomState.listeners.forEach((l) => l());
};
// writeAtom calls atom.write with the necessary params and triggers notify function
const writeAtom = (atom, value) => {
const atomState = getAtomState(atom);
// 'a' is some atom from atomStateMap
const get = (a) => {
const aState = getAtomState(a);
return aState.value;
};
// if 'a' is the same as atom, update the value, notify that atom and return else calls writeAtom for 'a' (recursively)
const set = (a, v) => {
if (a === atom) {
atomState.value = v;
notify(atom);
return;
}
writeAtom(a, v);
};
atom.write(get, set, value);
};
const notify = (atom) => {
const atomState = getAtomState(atom);
atomState.dependents.forEach((d) => {
if (d !== atom) notify(d);
});
atomState.listeners.forEach((l) => l());
};
// writeAtom calls atom.write with the necessary params and triggers notify function
const writeAtom = (atom, value) => {
const atomState = getAtomState(atom);
// 'a' is some atom from atomStateMap
const get = (a) => {
const aState = getAtomState(a);
return aState.value;
};
// if 'a' is the same as atom, update the value, notify that atom and return else calls writeAtom for 'a' (recursively)
const set = (a, v) => {
if (a === atom) {
atomState.value = v;
notify(atom);
return;
}
writeAtom(a, v);
};
atom.write(get, set, value);
};
์ต์ข ์ ์ผ๋ก ์๋์ ๊ฐ์ด ์ ๋ฆฌ๊ฐ ๋ฉ๋๋ค.
- ๊ฐ๊ฐ์ย
atom
์ยdependents
ย property๋ฅผ ํตํด ์์ ์๊ฒ ์์กด์ ์ธ atom๋ค์ ์ ์ฅํ๋ค. - atom์ ์ฝ์ ๋(read๊ฐ ์คํ๋์ด store์์ ํด๋น atom์ ๊ฐ์ ์ฝ์ ๋), ํด๋นย
atom
์ด ๋ค๋ฅธยatom
์ ์์กด์ ์ธ atom์ด๋ผ๋ฉด
, ์์กดํ๋ยatom
์ยdependents
์ ์ถ๊ฐํ๊ณ ์ฌ๊ท์ ์ผ๋กยatom
์ ๊ฐ์ ์ฝ๋๋ค atom
์ ๊ฐ์ ์ธ ๋, ํด๋นยatom
์ ์์กดํ๋ยatom
๋ค์๊ฒยnotify
๋ฅผ ํด์ฃผ์ด ๊ฐ๊ฐ์ยatom
๋ค์ด ์๋กญ๊ฒ ์ ๋ฐ์ดํธ๋ ๊ฐ์ ํ์ํ ์ ์๋๋ก ํ๋ค.