Recoil
React를 위한 상태 관리 라이브러리
설치
# npm
npm install recoil
# yarn
yarn add recoil
ESLint
eslint-plugin-react-hooks를 사용하는 경우 useRecoilCallback을 additionalHooks에 추가하는 것을 권장
useRecoilCallback()을 사용하기 위해 전달된 종속성이 잘못 지정되었을 때 경고와 해결 방안 제시해줌
{
"plugins": ["react-hooks"],
"rules": {
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": [
"warn",
{ // 추가
"additionalHooks": "useRecoilCallback"
}
]
}
}
사용
- RecoilRoot : recoil을 사용하기 위해 Root Component에 추가
import { RecoilRoot } from 'recoil';
function App() {
return (
<RecoilRoot>
<Main />
</RecoilRoot>
);
}
주요 개념
atoms(공유 상태)에서 selectors(순수 함수)를 거쳐 React Component로 내려가는 data-flow graph를 만들 수 있음
- Atoms : 컴포넌트가 구독할 수 있는 상태의 단위
- Selectors : atoms 상태 값을 동기 또는 비동기 방식을 통해 변환
Atoms
- 상태의 단위이며 업데이트와 구독이 가능
- atom이 업데이트되면 각각의 구독된 Component는 새로운 값을 반영해 다시 랜더링 됨
- 동일한 Atom이 여러 Component에서 사용되는 경우 모든 Component가 상태를 공유
생성
- key : 전역적으로 고유하도록 설정
- default : React Component 상태처럼 기본값 설정
const fontSizeState = atom({
key: 'fontSizeState',
default: 15,
});
사용
- useRecoilState : useState와 비슷하지만, 상태가 Component 간에 공유될 수 있다는 차이가 있음
function FontButton() {
const [fontSize, setFontSize] = useRecoilState(fontSizeState);
return (
<button onClick={() => setFontSize((size) => size + 1)} style={{fontSize}}>
Click to Enlarge
</button>
);
}
- useRecoilValue : atom을 읽기만 할 때 사용. atom이 Component를 등록하도록 함
- useSetRecoilState : atom에 쓰려고만 할 때 사용
- useResetRecoilState : atom을 초깃값으로 초기화할 때 사용
- useRecoilCallback : Component가 등록되지 않고 atom값을 읽어야 하는 경우
Selectors
- atoms나 다른 selectors를 입력으로 받아들이는 순수 함수
- 상위 atoms나 selectors가 업데이트되면 하위의 selector도 다시 실행됨
- Component들은 selectors를 atoms처럼 구독할 수 있고, selectors가 변경되면 Component들도 다시 랜더링 됨
- 최소한의 상태 집합만 atoms에 저장하고, 다른 모든 파생 데이터는 selectors에 명시한 함수를 통해서 쓸모없는 상태들의 보존을 방지
생성
- get : 계산될 함수
- get (인자) : atoms, 다른 selectors에 접근 가능
- get을 통해서 참조되는 다른 atoms나 selectors가 업데이트되면 이 함수도 다시 실행됨
const fontSizeLabelState = selector({
key: 'fontSizeLabelState',
get: ({get}) => {
const fontSize = get(fontSizeState);
const unit = 'px';
return `${fontSize}${unit}`;
},
});
- set : 쓰기 가능한 selector
사용
- useRecoilValue : 하나의 atom이나 selector를 인자로 받아 대응하는 값을 반환
function FontButton() {
const [fontSize, setFontSize] = useRecoilState(fontSizeState);
const fontSizeLabel = useRecoilValue(fontSizeLabelState);
return (
<>
<div>Current font size: ${fontSizeLabel}</div>
<button onClick={setFontSize(fontSize + 1)} style={{fontSize}}>
Click to Enlarge
</button>
</>
);
}
비동기 selector
- Selector는 비동기 함수를 사용할 수 있으며 Promise를 출력 값으로 반환 가능
const myQuery = selector({
key: 'MyQuery',
get: async ({get}) => {
return await myAsyncQuery(get(queryParamState));
},
});
- 비동기 Selector를 사용할 때는 Suspense, fallback 사용
function ResultsSection() {
return (
<React.Suspense fallback={<div>Loading...</div>}>
<ExampleApp />
</React.Suspense>
);
}
class Loadable
atom, selector의 최신 상태를 대표
사용 가능(hasValue)하거나 에러상태(hasError) 거나 로딩 상태(loading)이거나 셋 중 하나의 상태를 가짐
function UserInfo({userID}) {
const userNameLoadable = useRecoilValueLoadable(userNameQuery(userID));
switch (userNameLoadable.state) {
case 'hasValue':
return <div>{userNameLoadable.contents}</div>;
case 'loading':
return <div>Loading...</div>;
case 'hasError':
throw userNameLoadable.contents;
}
}
- useRecoilStateLoadable : 비동기 selector 값을 읽어올 때 사용
- useRecoilValueLoadable : 비동기 selector 값을 읽을 때 사용
Reference
반응형
'Project > Study' 카테고리의 다른 글
[Spring Boot] 빌드 도구 (0) | 2021.08.03 |
---|---|
[React] React-Query (0) | 2021.08.02 |
[WebSocket] Spring Boot + React WebSocket 코드 구현 (0) | 2021.07.26 |
Spring Boot 유효성 검사 (0) | 2021.07.20 |
Spring Session + Redis (0) | 2021.07.19 |
댓글