React recoil์์ ์ฌ์ฉํ๋ ๋ช๊ฐ์ง API์ ๋ํด ์์๋ณด๋ คํ๋ค.
์ฐ์ reoil ์ํ๋ฅผ ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ๋ ๋ถ๋ชจ ํธ๋ฆฌ์ RecoilRoot
์ ์ธ์ด ํ์ํ๋ค. React Native์์๋ ๋ฃจํธ ์ปดํฌ๋ํธ๊ฐ RecoilRoot
๋ฅผ ๋ฃ๊ธฐ์ ๊ฐ์ฅ ์ ํฉํ์ฌ, App.js
์ ์ ์ฉํ๋ค.
import React from 'react';
import {RecoilRoot} from 'recoil';
function App() {
return (
<RecoilRoot>
<Screen />
</RecoilRoot>
);
}
atom
์ Recoil์ ์ํ๋ฅผ ํํํ๋ค. atom()
ํจ์๋ ์ฐ๊ธฐ ๊ฐ๋ฅํ RecoilState
๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
function atom<T>({
key: string,
default: T | Promise<T> | RecoilValue<T>,
effects_UNSTABLE?: $ReadOnlyArray<AtomEffect<T>>,
dangerouslyAllowMutability?: boolean,
}): RecoilState<T>
key
: ๋ด๋ถ์ ์ผ๋ก atom์ ์๋ณํ๋๋ฐ ์ฌ์ฉ๋๋ ๊ณ ์ ํ ๋ฌธ์์ด
. ์ด ๋ฌธ์์ด์ ์ดํ๋ฆฌ์ผ์ด์
์ ์ฒด์์ ๋ค๋ฅธ atom๊ณผ selector์ ๋ํด ๊ณ ์ ํด์ผ ํ๋ค.default
: atom์ ์ด๊น๊ฐ
๋๋ Promise
๋๋ ๋์ผํ ํ์
์ ๊ฐ์ ๋ํ๋ด๋ ๋ค๋ฅธ atom์ด๋ selector
. effects_UNSTABLE
: atom์ ์ํ ์ ํ์ ์ธ Atom Effects
๋ฐฐ์ด.dangerouslyAllowMutability
: Recoil์ atom์ ์ด์ฉํด ๋ค์ ๋ ๋๋ง ๋๋ ์ปดํฌ๋ํธ์ ์ธ์ ์๋ ค์ผ ํ ์ง ์๊ธฐ ์ํด atom์ ์ํ ๋ณํ์ ์์กดํ๋ค. ๋ง์ฝ atom์ ๊ฐ์ด ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ, ์ด๋ฅผ ๊ฑฐ์น์ง ์๊ณ ๋ฑ๋ก๋ ์ปดํฌ๋ํธ์ ์ ๋๋ก ์๋ฆฌ์ง ์๊ณ ์ํ๊ฐ ๋ณ๊ฒฝ๋ ์ ์๋ค. ์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ์ ์ฅ๋ ๋ชจ๋ ๊ฐ์ด ๋ณ๊ฒฝ๋์ง ์๋๋ค. ๊ฒฝ์ฐ์ ๋ฐ๋ผ ์ด ์ต์
์ ์ฌ์ฉํ์ฌ ์ด ์ต์
์ ์ฌ์ ์ํ ์ ์๋ค.useRecoilState()
: atom์ ์ฝ๊ณ ์ฐ๋ ค๊ณ ํ ๋ ์ด Hook์ ์ฌ์ฉํ๋ค. ์ด Hook์ atom์ ์ปดํฌ๋ํธ๋ฅผ ๋ฑ๋กํ๋๋ก ํ๋ค.useRecoilValue()
: atom์ ์ฝ๊ธฐ๋ง ํ ๋ ์ด Hook์ ์ฌ์ฉํ๋ค. ์ด Hook์ atom์ ์ปดํฌ๋ํธ๋ฅผ ๋ฑ๋กํ๋๋ก ํ๋ค.useSetRecoilState()
: atom์ ์ฐ๋ ค๊ณ ๋ง ํ ๋ ์ด Hook๋ฅผ ์ฌ์ฉํ๋ค.useResetRecoilState()
: atom์ ์ด๊น๊ฐ์ผ๋ก ์ด๊ธฐํํ ๋ ์ด Hook์ ์ฌ์ฉํ๋ค.useRecoilCallback()
: ์ปดํฌ๋ํธ๊ฐ ๋ฑ๋ก๋์ง ์๊ณ atom์ ๊ฐ์ ์ฝ์ด์ผํ๋ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ค.** Hook API์ ๋ํด์ ๋ค์ ํฌ์คํธ์์ ์์ธํ ์์๋ณด๊ธฐ๋ก ํ์. **
import React from 'react';
import {View, Text, TouchableOpacity} from 'react-native';
import {atom, useRecoilState} from ' recoil';
const counter = atom({
ket: 'myCounter',
default: 0,
});
function Counter() {
const [count, setCount] = useRecoilState(counter);
const incrementByOne = () => setCount(count + 1);
return (
<View>
<Text>Count: ${count}</Text>
<TouchableOpacity onPress={()=> incrementByOne}>
<Text>Increment<Text>
</TouchableOpacity>
</View>
);
}
selector
๋ Recoil์์ ํจ์๋ ํ์๋ ์ํ
๋ฅผ ๋ํ๋ธ๋ค. ์ฃผ์ด์ง ์ข
์์ฑ ๊ฐ ์งํฉ์ ๋ํด ํญ์ ๋์ผํ ๊ฐ์ ๋ฐํํ๋ ๋ถ์์ฉ์ด ์๋ ์์ํจ์
๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค.
get
ํจ์๋ง ์ ๊ณต๋๋ฉด selector๋ ์ฝ๊ธฐ๋ง ๊ฐ๋ฅํ RecoilValueReadOnly
๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค. set
ํจ์๊ฐ ์ ๊ณต๋๋ฉด selector๋ ์ฐ๊ธฐ ๊ฐ๋ฅํ RecoilState
๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
function selector<T>({
key: string,
get: ({
get: GetRecoilValue
}) => T | Promise<T> | RecoilValue<T>,
set?: (
{
get: GetRecoilValue,
set: SetRecoilState,
reset: ResetRecoilState,
},
newValue: T | DefaultValue,
) => void,
dangerouslyAllowMutability?: boolean,
})
type ValueOfUpdater<T> = T | DefaultValue | ((prevValue: T) => T | DefaultValue);
type GetRecoilValue = <T>(RecoilValue<T>) => T;
type SetRecoilState = <T>(RecoilState<T>, ValueOrUpdater<T>) => void;
type ResetRecoilState = <T>(RecoilState<T>) => void;
key
: ๋ด๋ถ์ ์ผ atom์ ์๋ณํ๋๋ฐ ์ฌ์ฉ๋๋ ๊ณ ์ ํ ๋ฌธ์์ด. ์ด ๋ฌธ์์ด์ ์ดํ๋ฆฌ์ผ์ด์
์ ์ฒด์์ ๋ค๋ฅธ atom๊ณผ selector์ ๋ํด ๊ณ ์ ํด์ผ ํ๋ค. ์ง์์ฑ์ ์ํ์ฌ ์ฌ์ฉ๋๋ค๋ฉด ์คํ ์ ๋ฐ์ ๊ฑธ์ณ ์์ ์ ์ผ ํ์๊ฐ ์๋ค.get
: ํ์๋ ์ํ์ ๊ฐ์ ํ๊ฐํ๋ ํจ์. ๊ฐ์ ์ง์ ๋ฐํํ๊ฑฐ๋ ๋น๋๊ธฐ์ ์ธ Promise
๋ ๋๋ ๊ฐ์ ์ ํ์ ๋ํ๋ด๋ ๋ค๋ฅธ atom์ด๋ selector๋ฅผ ๋ฐํํ ์ ์๋ค. ์ฒซ ๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ก ๋ค์ ์์ฑ์ ํฌํจํ๋ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๋ค.๋ค๋ฅธ atom์ด๋ selector๋ก๋ถํฐ ๊ฐ์ ์ฐพ๋๋ฐ ์ฌ์ฉ๋๋ ํจ์. ์ด ํจ์์ ์ ๋ฌ๋ ๋ชจ๋ atom๊ณผ selector๋ ์์์ ์ผ๋ก selector์ ๋ํ __์์กด์ฑ__ ๋ชฉ๋ก์ ์ถ๊ฐ๋๋ค.. Selector์ ์์กด์ฑ์ด ๋ณ๊ฒฝ๋๋ฉด Selector๊ฐ ๋ค์ ํ๊ฐ๋๋ค.
set?
: ์ด ์์ฑ์ด ์ค์ ๋๋ฉด selector๋ ์ฐ๊ธฐ ๊ฐ๋ฅํ ์ํ๋ฅผ ๋ฐํํ๋ค. ์ฒซ ๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ก ์ฝ๋ฐฑ ๊ฐ์ฒด์ ์๋ก ์
๋ ฅ ๊ฐ์ด ์ ๋ฌ๋๋ค. ์ฌ์ฉ์๊ฐ selector๋ฅผ ์ฌ์ค์ ํ ๊ฒฝ์ฐ ์๋ก ์
๋ ฅ ๊ฐ์ T
ํ์
์ ๊ฐ ๋๋ DefaultValue
ํ์
์ ๊ฐ์ฒด์ผ ์ ์๋ค. ์ฝ๋ฐฑ์๋ ๋ค์์ด ํฌํจ๋๋ค.
get
- ๋ค๋ฅธ atom์ด๋ selector๋ก๋ถํฐ ๊ฐ์ ์ฐพ๋๋ฐ ์ฌ์ฉ๋๋ ํจ์. ์ด ํจ์๋ selector๋ฅผ ์ฃผ์ด์ง atom์ด๋ selector๋ฅผ ๊ตฌ๋
ํ์ง ์๋๋ค.
set
- ์
์คํธ๋ฆผ Recoil ์ํ์ ๊ฐ์ ์ค์ ํ ๋ ์ฌ์ฉ๋๋ ํจ์. ์ฒซ ๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ Recoil ์ํ, ๋ ๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ ์๋ก์ด ๊ฐ์ด๋ค. ์๋ก์ด ๊ฐ์ ์
๋ฐ์ดํธ ํจ์๋ ์ฌ์ค์ ์ก์
์ ์ ํํ๋ DefaultValue
๊ฐ์ฒด์ผ ์ ์๋ค.
dangerouslyAllowMutability
: Selector๋ ํ์๋ ์ํ์ ์์ ํจ์ ๋ฅผ ํ๋๋ด๋ฉฐ ํญ์ ๋์ผํ ๊ฐ์ ๋ฐํํด์ผ ํ๋ค. ์ด๋ฅผ ๋ณดํธํ๊ธฐ ์ํด selector์ ์ ์ฅ๋ ๋ชจ๋ ๊ฐ์ ๊ธฐ๋ณธ์ ์ผ๋ก ๊ณ ์ ๋์ด ์๋ค. ๊ฒฝ์ฐ์ ๋ฐ๋ผ ์ด ์ต์
์ ์ฌ์ฉํ์ฌ ์ฌ์ ์ํด์ผ ํ ์ ์๋ค.
์ฝ๊ธฐ๋ง ๊ฐ๋ฅํ selector๋ ์์กด์ฑ์ ๊ธฐ์ค์ผ๋ก selector์ ๊ฐ์ ํ๊ฐํ๋ get
๋ฉ์๋๋ฅผ ๊ฐ๋๋ค. ์์กด์ฑ ์ค ์ด๋ ํ ๊ฒ์ด ์
๋ฐ์ดํธ ๋๋ฉด selector๋ ๋ค์ ํ๊ฐ๋๋ค. Selector๋ฅผ ํ๊ฐํ ๋ ์ค์ ๋ก ์ฌ์ฉํ๋ atom์ด๋ selector๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์กด์ฑ์ด ๋์ ์ผ๋ก ๊ฒฐ์ ๋๋ค. ์ด์ ์์กด์ฑ์ ๊ฐ์ ๋ฐ๋ผ ๋ค๋ฅธ ์ถ๊ฐ์ ์ธ ์์กด์ฑ์ ๋์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค. Recoil์ Selector๊ฐ ํ์ฌ ์
๋ฐ์ดํธ๋์ด์ง ์์กด์ฑ ์งํฉ๋ง ๊ตฌ๋
ํ๋๋ก ํ์ฌ ๋ฐ์ดํฐ ํ๋ฆ ๊ทธ๋ํ๋ฅผ ์๋์ ์ผ๋ก ์
๋ฐ์ดํธํ๋ค.
์๋ ์์์์ mySelector
๋ toggleState
atom๋ฟ๋ง ์๋๋ผ toggleState
์ ์์กดํ๋ selectorA
๋๋ selectorB
selector๋ ์์กดํ๋ค.
const toggleState = atom({ key: 'Toggle', default: false });
const mySelector = selector({
key: 'MySelector',
get: ({get}) => {
const toggle = get(toggleState);
if (toggle) {
return get(selectorA);
} else {
return get(selectorB);
}
});
์๋ฐฉํฅ selector๋ ์
๋ ฅ ๊ฐ์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ๊ณ ๋ฐ์ดํฐ ํ๋ฆ ๊ทธ๋ํ๋ฅผ ๋ฐ๋ผ ์
์คํธ๋ฆผ์์ ๋ณ๊ฒฝ์ฌํญ์ ์ ํํ๋ ๋ฐ ์ฌ์ฉํ ์ ์๋ค. ์ฌ์ฉ์๊ฐ selector๋ฅผ ์ ๊ฐ์ผ๋ก ์ค์ ํ๊ฑฐ๋ selector๋ฅผ ์ฌ์ค์ ํ ์ ์๊ธฐ ๋๋ฌธ์ ์
๋ ฅ ๊ฐ์ selector๊ฐ ๋ํ๋ด๋ ํ์
๊ณผ ๋์ผํ๊ฑฐ๋ ์ฌ์ค์ ์์
์ ๋ํ๋ด๋ DefaultValue
๊ฐ์ฒด ์ค ํ๋์ด๋ค.
์ด ๊ฐ๋จํ selector๋ ๊ธฐ๋ณธ์ ์ผ๋ก atom์ ๊ฐ์ธ์ ํ๋๋ฅผ ์ถ๊ฐํ๋ค. ์ด๊ฒ์ ๋จ์ง ์ค์ ๊ณผ ์ฌ์ค์ ์์ ์ ์ ์คํธ๋ฆผ atom๊น์ง ํต๊ณผํ๋ค.
const proxySelector = selector({
key: 'ProxySelector',
get: ({get}) => ({...get(myAtom), extraField: 'hi'}),
set: ({set}, newValue) => set(myAtom, newValue),
});
์ด selector๋ ๋ฐ์ดํฐ๋ฅผ ๋ณํํ๋ฏ๋ก ์
๋ ฅ ๊ฐ์ด DefaultValue
์ธ์ง ํ์ธํด์ผ ํ๋ค.
const transformSelector = selector({
key: 'TranformSelector',
get: ({get}) => get(myAtom) * 100,
set: ({set}, newValue) =>
set(myAtom, newValue instanceof DefaultValue ? newValue : newValue / 100),
});
Selector๋ ๋ํ ๋น๋๊ธฐ ํ๊ฐ ํจ์๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ Promise
๋ฅผ ์ถ๋ ฅ๊ฐ์ผ๋ก ๋ฐํํ ์ ์๋ค.
const myQuery = selector({
key: 'MyQuery',
get: async ({get}) => {
return await myAsyncQuery(get(queryParamState));
},
});
https://recoiljs.org/ko/docs/api-reference/core/atom
https://recoiljs.org/ko/docs/api-reference/core/selector