๐ฏ
Recoil์ ์ฌ์ฉํ ์ ์๋ค.
โ Recoil์ด๋?
Recoil์ React ํ๋ก์ ํธ๋ฅผ ์ํ ๋ง์ ์ ์ญ ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค ์ค ํ๋๋ก, 2020๋ 5์ Facebook์์ ์ถ์ํ์๋ค. ๊ทธ๋ ๊ธฐ์, ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(Redux, Mobx)์๋ ๋ฌ๋ฆฌ React ์ ์ฉ์ด๋ฉฐ React์ ์ต์ ํ๋์ด ์๋ค๊ณ ํ ์ ์๋ค.
Recoil์ ์ฌ์ฉํ๋ฉด atoms(๊ณต์ ์ํ)์์ selector(์์ ํจ์)๋ฅผ ๊ฑฐ์ณ React component๋ก ํ๋ฅด๋ data-flow graph๋ฅผ ๋ง๋ค ์ ์๋ค. ์ด๋ atoms๋ component๋ฅผ ๊ตฌ๋ ํ ์ ์๋ ์ํ์ ๋จ์๊ณ selector์ ์ด ์ํ๋ฅผ ๋๊ธฐ์ ๋๋ ๋น๋๊ธฐ์์ผ๋ก ๋ณํํ๋ค.
โ Recoil์ ์ฌ์ฉํ๋ ์ด์
recoil์ด ์๋ ๋ค๋ฅธ ์ ์ญ ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด ๋ง์์๋ ๋ถ๊ตฌํ๊ณ ๋ช๊ฐ์ง ๋จ์ ๋ค์ด ์กด์ฌํ์๋ค.
- React ์ ์ฉ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋๊ธฐ ๋๋ฌธ์ React ๊ด์ ์์ ์ธ๋ถ์์ธ์ผ๋ก Store๊ฐ ์ทจ๊ธ๋๋ฉฐ, ๋์์ฑ ๋ชจ๋๋ฅผ ๊ตฌํํ๊ธฐ์ ํธํ์ฑ์ด ๋ถ์กฑํ๋ค.
- Store, Action, Reducer ๋ฑ ์ฌ์ ์ ์ค๋นํด์ผํ๋ ๋ณต์กํ Boiler Plate ์ด๊ธฐ์ธํ ์ ๊ฒฐ๊ตญ ๋นํจ์จ์ ์ด๋ฉฐ ๋ฌ๋์ปค๋ธ๊ฐ ๋๋ค.
- Redux-saga ๋ฑ ์ ์ญ์ํ์ ๋น๋๊ธฐ ๋ฐ์ดํฐ๋ฅผ ํธ์ถํ๊ธฐ ์ํ ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ์ํ๋ค. ์ฆ, ๋น๋๊ธฐ ๋ฐ์ดํฐ์ ์ถ๊ฐ ๋ฆฌ์์ค๊ฐ ์๊ตฌ๋๋ค๋ค.
์ด๋ฌํ ๋จ์ ๋ค์ ํด๊ฒฐํ๊ธฐ ์ํด recoil์ด ๋ํ๋ฌ๊ณ ๊ฐ์ฅ ์ข์ ์ฅ์ ์ Boiler Plate ์์ด ํ์ ํ ์ ๋ค๋ ์ ์ด๋ค.
โ Recoil ์ฅ/๋จ์
๐ข Recoil ์ฅ์
- ๋น๋๊ธฐ๋ฌธ์ ๋ฅผ ๊น๋ํ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ค.
- ๋๊ธฐ์ํ๋ฅผ ๋ค๋ฃจ๋ฏ์ด ์ฒ๋ฆฌํ๊ณ , ๊ท์ฐฎ์ ๋น๋๊ธฐ์ํ ์ฒ๋ฆฌ๋ Suspense์ ์์ํ๋ค.
- ์ฝ๋์ ๋ณต์ก๋๋ฅผ ์ค์ผ ์ ์๋ค.
- ๋จ์ํ๋ค
- ๋ฆฌ๋์ค์ action, dispatch, reducer, store, ๋น๋๊ธฐ๋ฅผ ์ํ thunk, saga... ๋ณต์กํ๋ค
- ๋ฆฌ์ฝ์ผ์ atom, selector ๋๊ฐ๊ฐ ์ฌ์ค์ ๋์ด๋ค. ๋จ์ํ๋ค
- ๊ณผ์ฐ ๋ฆฌ๋์ค ์ด์ฌ์์๊ฒ ๋ฆฌ๋์ค๋ฅผ ์๊ฐํ ๋๋ ์ด ๊ธ์ฒ๋ผ ์งง๊ฒ ์ค๋ช ํ ์ ์์๊น?
- ๋ฆฌ์กํธ์ ๊ฐ๋ฐ ๋ฐฉํฅ์ฑ์ด ๊ฐ๋ค
- 2๋ ๋ฐ ์ ์ ๋ฑ์ฅํ ๋ฆฌ์กํธ์ hooks๊ฐ ์ฒ์ ๋์์๋๋ฅผ ์๊ฐํด๋ณด๋ผ
- ์ฒ์์๋ Class๊ธฐ๋ฐ ์ปดํฌ๋ํธ์ ์ต์ํด์ ๊ฑฐ๋ถ๊ฐ์ด ์์๋ค.
- ํ์ง๋ง hooks๊ฐ ์ ์ธ์ ์ธ API๋ก ์ฝ๋๋ฅผ ์ผ๋ง๋ ๋จ์ํ๊ฒ ๋ฐ๊ฟ์ฃผ์๋์ง ์๊ฐํด๋ณด๋ผ
- recoil์ ๋ํ๋ฒ ์ ์ธ์ ์ธ API๋ก ์ฝ๋๋ฅผ ๋จ์ํ๊ฒ ๋ฐ๊พธ๋ ค ํ๊ณ ์๋ค.
- ์ฌ์ค ์ฝ๋๋ฅผ ๋จ์ํ๊ฒ ๋ฐ๊พธ๋๊ฒ ์ด์์ ์์๊ฐ ์๋ค.
- ์ ์ธ์ ํ๋ก๊ทธ๋๋ฐ
- ๋น๋๊ธฐ์ฒ๋ฆฌ๋ฅผ ์์๋ฐ์ ์ฒ๋ฆฌํ๋ ์ปดํฌ๋ํธ๋ฅผ JSX๋ก ์ ์ธํจ์ผ๋ก์จ ๋ชจ๋ ๋น๋๊ธฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ค.
- ๋ด์ฉ์ด ๊ธธ์ด์ ธ ๊ธ์ ๋ด์ง ๋ชปํ ์ฅ์ ๋ค
- ์บ์ฑ๊ธฐ๋ฅ์ผ๋ก ๋น๋๊ธฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ฅผ ๋น ๋ฅด๊ฒ ํจ
- ์ํ๋ฅผ ๋ถ์ฐ์ ์ผ๋ก ๋ ์ ์๊ธฐ ๋๋ฌธ์ ์ฝ๋ ์คํ๋ฆฌํ ์ด ๊ฐ๋ฅํจ
๐ด Recoil ๋จ์
- ์์ ์ฑ์ ๋ํ ๊ฑฑ์
- ๋ ํฌ์งํ ๋ฆฌ๊ฐ facebook/Recoil์ด ์๋๊ณ facebookexperimental/Recoil์ด๋ค.
- ์คํ์ ์ธ API๋ค
- recoil์ api์ค์๋ ์์ง๋ _UNSAFE surfix๊ฐ ๋ถ์๊ฒ์ด ๋ง๋ค
- ํ์ง๋ง ๋น ๋ฅธ ์๋๋ก UNSAFE ๋ฑ์ง๊ฐ ๋ผ์ง๊ณ ์๋ค.
- devtools์ ๋ถ์ฌ
- ๋ฆฌ๋์ค์ devtools ๋งํผ ํ๋ฅญํ ๋๋ฒ๊น ํด์ด ์์ง ์๋ค.
- ๋น๊ณต์ devtools ํ๋ฌ๊ทธ์ธ์ด ์๊ธฐ๋ ํ๋ฐ ํ๋ฆฌํฐ๊ฐ ์ข์ง๋ ์๋ค
- ๊ด๋ จ ์คํ์์ค ์ํ๊ณ๊ฐ redux์ ๋นํด์ ๋ถ์กฑํ๋ค
- ์๋ฌด๋๋ redux๊ฐ ์ค๋๋๊ณ ์ฌ์ฉ๊ธฐ์ ์ด ๋ง๋ค๋ณด๋ ๊ด๋ จ ์คํ์์ค๊ฐ ํ๋ฐํ๋ค
- localStorage์ ์ฐ๋ํ์ฌ ์ํ๋ฅผ ์ ์ง์ํค๋ persist ๊ด๋ จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ณด์
- redux-persist โญ๏ธ 12K
- recoil-persist โญ๏ธ 213
- ๊ธฐ๋ฅ์ด ์ข ๋ธ๋ฆฐ๋ค. migration์ด ์๋ค
โ Recoil ์์ ๋ฅผ ๋ง๋ค๊ธฐ ์์
โ RecoilRoot
๋ฆฌ์ฝ์ผ state๋ฅผ ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ๋ค์ <RecoilRoot>๋ฅผ ํ์๋ก ํ๋ค. <RecoilRoot>๋ฅผ ์ฌ์ฉํ๋ ๊ฐ์ฅ ์ข์๊ณณ์ root component์ด๋ค.
import { RecoilRoot } from "recoil";
import Counter from "./Counter";
function App() {
return (
<RecoilRoot>
<Counter />
</RecoilRoot>
);
}
export default App;
โ Atom
์ํฐ์ ์ํ๋ฅผ ๋งํ๋ฉฐ ์ด๋ ํ ์ปดํฌ๋ํธ์์ ์์ฌ์ง๊ณ ์ฝํ์ง ์ ์๋ค. ์ํฐ์ ๋ฐธ๋ฅ๋ฅผ ์ฝ๋ ์ปดํฌ๋ํธ๋ค์ ์๋ฌต์ ์ผ๋ก ๊ทธ ์ํฐ์๊ฒ subscribe๋์ด์ง๊ณ ์๋ค. ๊ทธ๋์ ์ํฐ์ ์ ๋ฐ์ดํธ๋ ์ด ์ํฐ์ ์ฐธ๊ณ ํ๊ณ ์๋ ์ปดํฌ๋ํธ๋ฅผ re-render์ํจ๋ค.
import { atom } from "recoil";
let countState = atom({
key: "counter",
default: 0,
});
export default countState;
โ Selector
Recoil์ selector API๋ฅผ ์ ๊ณตํ๋ค. React์ useMemo, Redux์ selector ์ฒ๋ผ ๋ค๋ฅธ ์ํ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ์๋ ์ํ(derived state) ๋ง๋ค์ด๋ด๋ ์ญํ ์ ํ๋ค. ์๋ฅผ ๋ค๋ฉด ์์ ๋ชฉ๋ก์์ ์๋ฃ๋ ์์ ๋ง ํํฐ๋ง ํ๊ณ ์ถ์ ๋ ์ฌ์ฉํ ์ ์๋ค.
(์ด๋ฒ ์์ ์์๋ recoil์ ๊ฐ์ฅ ๊ฐ๋จํ ๋ํ๋ด๊ธฐ ์ํด ์๋ตํ๋ค.)
โ useRecoilState
useState์ ๊ฐ์ ์ญํ ์ด๋ผ๊ณ ๋ด๋ ๋ ๊ฑฐ ๊ฐ๋ค. ๊ทธ๋ฌ๋ ๋ค๋ฅธ ํ์ผ์ ์๋ ์ํฐ์ ์ฝ์ ์ ์๋ค๋ ์ ์์ useSelector์ ๋น์ทํ๊ฑฐ ๊ฐ๊ธฐ๋ ํ๋ค.
๋ค์ ๋งํด์, ์ํฐ์ ์ํ๋ฅผ ์ค์ ํ ์ ์๊ณ , ๋ณ๊ฒฝ ์ํฌ ์ ๋ ์๋ค.
โ useRecoilValue
์ํฐ์ ์กฐํํ ๋๋ง ์ฌ์ฉํ๋ค.
โ useSetRecoilState
setter ์ญํ ์ ํ๋ค. useSetRecoilState๋ฅผ ์ฌ์ฉํ์ฌ ์ํฐ์ ๋ณ๊ฒฝ ์ํฌ ์ ์๋ค.
โ useResetRecoilState
์ํฐ ๊ฐ์ ๋ํดํธ ๊ฐ์ผ๋ก ๋ณ๊ฒฝ์์ผ์ค๋ค.
โ Recoil ์์
Recoil์ ์ด์ฉํ์ฌ counter์ ๋ง๋ค์ด ๋ณด๊ณ ์ ํ๋ค.
[App.js]
Recoil์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ RecoilRoot๋ฅผ ๊ฐ์ธ์ฃผ์ด์ผ ํ๋ค.
import { RecoilRoot } from "recoil";
import Counter from "./Counter";
function App() {
return (
<RecoilRoot>
<Counter />
</RecoilRoot>
);
}
export default App;
[Atom.js]
Recoil์ ํตํด ์ํ ๊ด๋ฆฌ๋ฅผ ํ๊ธฐ ์ํด์ atom์ ๋ง๋ค์ด์ค๋ค. ์ด๋ countState๋ deafult๊ฐ 0์ธ atom์ด๋ค.
import { atom } from "recoil";
let countState = atom({
key: "counter",
default: 0,
});
export default countState;
[Counter.js]
Counter๋ฅผ ์ํ ์ปดํฌ๋ํธ์ด๋ค.
์ฌ๊ธฐ์๋ recoil์ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ธฐ(get) ์ํด useRecoilValue ๋ฅผ ์ฌ์ฉํ์๊ณ
๋ฐ์ดํฐ๋ฅผ ์ฐ๊ธฐ(set) ์ํด์๋ useSetRecoilState ๋ฅผ ์ฌ์ฉ
default๊ฐ์ผ๋ก ๋ฆฌ์
ํ๊ธฐ ์ํด์๋ useResetRecoilState ๋ฅผ ์ฌ์ฉํ์๋ค.
import { useRecoilValue, useResetRecoilState, useSetRecoilState } from "recoil";
import countState from "./Atom";
function Counter() {
const count = useRecoilValue(countState); // useRecoilValue : get only
const handleCount = useSetRecoilState(countState); // useSetRecoilState : set only
const handleResetCount = useResetRecoilState(countState); // useResetRecoilState : reset default
const handlePlus = () => {
handleCount((count) => count + 1);
};
const handleMinus = () => {
handleCount((count) => count - 1);
};
const handleReset = () => {
handleResetCount();
};
return (
<div>
<h2>Recoil Counter</h2>
<div>{count}</div>
<button onClick={handlePlus}>+</button>
<button onClick={handleMinus}>-</button>
<button onClick={handleReset}>reset</button>
</div>
);
}
export default Counter;
https://abangpa1ace.tistory.com/212
https://velog.io/@gomjellie/3%EB%B6%84-Recoil#recoil-%EB%8B%A8%EC%A0%90
'Basic > React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[React] SPA ํ๋ ์ ์ํฌ (0) | 2023.01.24 |
---|---|
[React] local์์ ์คํ ์ render๊ฐ ๋ ๋ฒ ๋๊ณ ์์ด์! (0) | 2023.01.23 |
[React] infinity scroll ๋ฌดํ ์คํฌ๋กค ๋ง๋ค๊ธฐ (0) | 2023.01.15 |
[React] outlet์ ์ด์ฉํ ์ฌ์ด ๋ ์ด์์ ๊ต์ฒด (0) | 2023.01.15 |
[React] Custom hook ๋ชจ์ (0) | 2023.01.02 |