DevYoon
[Recoil] Recoil์ด๋? ๋ณธ๋ฌธ
๐พ Recoil
1๏ธโฃ Recoil์ด๋?
React์ hooks์ ์ด์ธ๋ฆฌ๋ฉด์, React์ ํ์ํ ๊ฒ๋ค๋ง React์ค๋ฝ๊ฒ ์ ์ํ ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
๊ธฐ์กด์ Redux๋ Mobx์ ๊ฐ์ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ React ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋
store๋ ์ธ๋ถ์์ธ์ผ๋ก ์ทจ๊ธ๋๋ฏ๋ก, React์ ๋ด๋ถ ์ค์ผ์ค๋ฌ์ ์ ๊ทผํ ์ ์์
๋์์ฑ ๋ชจ๋์ ๋ฑ์ฅ์ผ๋ก ์ ์ฌ์ค์ด ์ค์ํด์ง
๋์์ฑ ๋ชจ๋ โ
ํ๋ก๊ทธ๋จ์ ๋ ๋ฆฝ์ ์ผ๋ก ์คํํ ์ ์๋ ์กฐ๊ฐ์ผ๋ก ๋๋์ด ๊ตฌ์กฐํ
โก๏ธ ๋จ์ผ ์ค๋ ๋ ์ฌ์ฉ์ ํ๊ณ๋ฅผ ๊นจ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณด๋ค ํจ์จ์ ์ผ๋ก ๋ง๋ฆ
์ฐธ๊ณ ๐ https://medium.com/swlh/what-is-react-concurrent-mode-46989b5f15da
๊ธฐ๋ณธ์ ์ธ store ๊ตฌ์ฑ์ ์ํด ๋ง์ ๋ณด์ผ๋ฌ ํ๋ ์ดํธ์ ์ฅํฉํ ์ฝ๋๋ฅผ ์์ฑํด์ผ ํจ
๋น๋๊ธฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋๋ ๊ณ์ฐ๋ ๊ฐ ์บ์์ ๊ฐ์ ์ค์ํ ๊ธฐ๋ฅ์ ํด๊ฒฐํ๊ธฐ ์ํด์๋ ๋ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ผ ํจ
2๏ธโฃ ์ค์น
// npm ์ฌ์ฉ ์
npm install recoil
// yarn ์ฌ์ฉ ์
yarn add recoil
3๏ธโฃ recoilRoot
import React from 'react';
import {
RecoilRoot,
atom,
selector,
useRecoilState,
useRecoilValue,
} from 'recoil';
function App() {
return (
<RecoilRoot>
<CharacterCounter />
</RecoilRoot>
);
}
- recoil state๋ฅผ ์ฌ์ฉํ ์ปดํฌ๋ํธ๋ฅผ RecoilRoot ํ๊ทธ๋ก ๊ฐ์ธ์ฃผ์ด์ผ ํจ
4๏ธโฃ Atom
์ปดํฌ๋ํธ๊ฐ ๊ตฌ๋ ํ ์ ์๋ React state, ํ๋์ ์ํ
- atom์ ๊ฐ์ ๋ณ๊ฒฝํ๋ฉด ๊ทธ๊ฒ์ ๊ตฌ๋ ํ๊ณ ์๋ ์ปดํฌ๋ํธ๋ค์ด ๋ชจ๋ ๋ค์ ๋ ๋๋ง๋จ
- ์ํฐ์ ์์ฑํ๊ธฐ ์ํด์๋ ์ดํ๋ฆฌ์ผ์ด์ ์์ ๊ณ ์ ํ ํค ๊ฐ๊ณผ ๋ํดํธ ๊ฐ์ ์ค์ ํด์ผ ํจ
- ๋ํดํธ ๊ฐ์ ์ ์ ์ธ ๊ฐ, ํจ์, ๋น๋๊ธฐ ํจ์(์ถํ ์ง์) ๋ฑ์ด ๋ ์ ์๋ค
export const nameState = atom({
key: 'nameState',
default: 'Yoonju Kim'
});
useRecoilState
atom์ ๊ฐ์ ๊ตฌ๋ ํ์ฌ ์ ๋ฐ์ดํธํ ์ ์๋ hook์ผ๋ก, useState์ ๋์ผํ ๋ฐฉ์
useRecoilValue
setter ํจ์ ์์ด atom์ ๊ฐ๋ง ๋ฐํํจ
useSetRecoilState
setter ํจ์๋ง ๋ฐํํจ
import {nameState} from './someplace'
// useRecoilState
const NameInput = () => {
const [name, setName] = useRecoilState(nameState);
const onChange = (event) => {
setName(event.target.value);
};
return <>
<input type="text" value={name} onChange={onChange} />
<div>Name: {name}</div>
</>;
}
// useRecoilValue
const SomeOtherComponentWithName = () => {
const name = useRecoilValue(nameState);
return <div>{name}</div>;
}
// useSetRecoilState
const SomeOtherComponentThatSetsName = () => {
const setName = useSetRecoilState(nameState);
return <button onClick={() => setName('Jon Doe')}>Set Name</button>;
}
5๏ธโฃ Selector
์ํ์์ ํ์๋ ๋ฐ์ดํฐ๋ก, ๋ค๋ฅธ atom์ ์์กดํ๋ ๋์ ์ธ ๋ฐ์ดํฐ๋ฅผ ๋ง๋ค ์ ์๊ฒ ํด์ค
- get
- set : ํ๋ ์ด์์ atom์ ์ ๋ฐ์ดํธํ ์ ์์
// ๋๋ฌผ ๋ชฉ๋ก ์ํ
const animalsState = atom({
key: 'animalsState',
default: [{
name: 'Rexy',
type: 'Dog'
}, {
name: 'Oscar',
type: 'Cat'
}],
});
// ํํฐ๋ง ๋๋ฌผ ์ํ
const animalFilterState = atom({
key: 'animalFilterState',
default: 'dog',
});
// ํ์๋ ๋๋ฌผ ํํฐ๋ง ๋ชฉ๋ก
const filteredAnimalsState = selector({
key: 'animalListState',
get: ({get}) => {
const filter = get(animalFilterState);
const animals = get(animalsState);
return animals.filter(animal => animal.type === filter);
}
});
// ํํฐ๋ง๋ ๋๋ฌผ ๋ชฉ๋ก์ ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ
const Animals = () => {
const animals = useRecoilValue(filteredAnimalsState);
return animals.map(animal => (<div>{ animal.name }, { animal.type }</div>));
}
์ฐธ๊ณ ๐ https://codesandbox.io/s/hik7u?file=/src/App.js
โ ์ฐธ๊ณ ๊ธ ๋ชฉ๋ก
Recoil ๊ณต์ ๋ฌธ์ ๐ https://recoiljs.org/ko/docs/introduction/installation
Recoil - ๋ ๋ค๋ฅธ React ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ? ๐ https://ui.toast.com/weekly-pick/ko_20200616#%EC%B6%94%EA%B0%80-%EC%9D%BD%EC%9D%84-%EA%B1%B0%EB%A6%AC
React์ค๋ฌ์ด ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ :: Recoil ๐ https://velog.io/@juno7803/React%EC%8A%A4%EB%9F%AC%EC%9A%B4-%EC%83%81%ED%83%9C%EA%B4%80%EB%A6%AC-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-Recoil
Recoil 200% ํ์ฉํ๊ธฐ ๐ https://velog.io/@juno7803/Recoil-Recoil-200-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0
What is React Concurrent Mode? ๐ https://medium.com/swlh/what-is-react-concurrent-mode-46989b5f15da