페이스북이 만든 상태관리 라이브러리 Recoil
리액트의 상태 관리를 하는 방법은 여러 가지가 있지만,
새로 다뤄야 하는 Recoil에 대해 공부한 내용을 기록한다.
공식문서: Recoil을 사용하면 atoms (공유 상태)에서 selectors (순수 함수)를 거쳐 React 컴포넌트로 내려가는 data-flow graph를 만들 수 있다.
Atoms는 컴포넌트가 구독할 수 있는 상태의 단위다.
Selectors는 atoms 상태값을 동기 또는 비동기 방식을 통해 변환한다.
redux와 비교해보면, Atoms는 store, Selectors는 action 함수인가? 🤔
npm install recoil
recoil 상태를 사용하는 컴포넌트는 부모 트리 어딘가에 나타나는 RecoilRoot 가 필요하다.
루트 컴포넌트가 RecoilRoot를 넣기에 가장 좋은 장소다.
import React from 'react';
import {
RecoilRoot,
atom,
selector,
useRecoilState,
useRecoilValue,
} from 'recoil';
function App() {
return (
<RecoilRoot>
<CharacterCounter />
</RecoilRoot>
);
}
상태 정의하기
atom
이 업데이트되면 각각의 구독된 컴포넌트는 새로운 값을 반영하여 다시 렌더링 된다. atom
이 여러 컴포넌트에서 사용되는 경우 모든 컴포넌트는 상태를 공유한다.atom
함수를 사용해 생성
atom
함수에key
와default
로 기본값 설정
key
는 고유해야 하며default
초기값은 비워도 된다const fontSizeState = atom({
key: 'fontSizeState',
default: 14,
});
// 또는
const fontState = atom({
key: 'fontState',
default: {
idx: 0,
name: 'subTitle',
size: 18,
color: 'blue'
}
});
atom
호출atom을 읽고 쓰려면
useRecoilState
라는 훅을 사용.
useState
와 비슷하지만 상태가 컴포넌트 간에 공유될 수 있다는 차이가 있다.
import { atom } form 'recoil';
function FontButton() {
const [fontSize, setFontSize] = useRecoilState(fontSizeState);
return (
<button onClick={() => setFontSize((size) => size + 1)} style={{fontSize}}>
Click to Enlarge
</button>
);
}
// 버튼을 클릭하면 버튼의 글꼴 크기가 1만큼 증가하며,
// fontSizeState atom을 사용하는 다른 컴포넌트의 글꼴 크기도 같이 변화한다.
function Text() {
const [fontSize, setFontSize] = useRecoilState(fontSizeState);
return <p style={{fontSize}}>This text will increase in size too.</p>;
}
getter와 setter를 직접 정의해서 사용할 수 있는 순수함수.
Selector
컴포넌트의 관점에서 보면
selectors
와atoms
는 동일한 인터페이스를 가지므로 서로 대체할 수 있다.
Selectors
생성Selectors는
selector
함수를 사용해 정의
const fontSizeLabelState = selector({
key: 'fontSizeLabelState',
get: ({get}) => {
const fontSize = get(fontSizeState);
const unit = 'px';
return `${fontSize}${unit}`;
},
});
Recoil에서는 특이하게 읽기 전용 함수와 쓰기 전용 함수를 제공한다.
Selectors
는 useRecoilValue()
를 사용해 읽을 수 있다useRecoilValue
읽기 전용 함수 예제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>
</>
);
}
useSetRecoilState
쓰기 전용 함수 예제
reference 학습할 때 좀 더 공부해보자..😅
const setList = useSetRecoilState(productsState);
Recoil에서는 reset 함수를 추가로 제공한다.
// ... 생략
const resetProducts = useResetRecoilState(productsState);
useEffect(() => {
return () => resetProducts(); // 언마운트 될 때 초기화
}, []);