22.2.7 (월) +15days
Recoil
Minimal and Reactish
Data Flow Grpah
Cross App Observation
소개
동기
호환성 및 단순함을 이유로 외부의 글로벌 상태관리 라이브러리보다는 React 자체에 내장된 상태 관리 기능을 사용하는 것이 가장 좋다. 그러나 React는 다음과 같은 한계가 있다.
- 컴포넌트의 상태는 공통된 상위요소까지 끌어올림으로써 공유될 수 있지만, 이 과정에서 거대한 트리가 다시 렌더링되는 효과를 야기하기도 한다.
- Context는 단일 값만 저장할 수 있으며, 자체 소비자(consumer)를 가지는 여러 값들의 집합을 담을 수는 없다.
- 이 두가지 특성이 트리의 최상단(state가 존재하는 곳)부터 트리의 잎(state가 사용되는 곳)까지의 코드 분할을 어렵게한다.
우리는 API와 의미 및 동작을 가능한 React답게 유지하면서 이것을 개선하고자 한다.
Recoil은 직교하지만 본질적인 방향 그래프를 정의하고 React 트리에 붙인다. 상태 변화는 이 그래프의 뿌리(atoms라고 부르는)로부터 순수함수(selectors라고 부르는 것)를 거쳐 컴포넌트로 흐르며, 다음과 같은 접근 방식을 따른다.
- 우리는 공유상태(shared state)도 React의 내부상태(local state)처럼 간단한 get/set 인터페이스로 사용할 수 있도록 boilerplate-free API를 제공한다. (필요한 경우 reducers 등으로 캡슐화할 수도 있다.)
- 우리는 동시성 모드(Concurrent Mode)를 비롯한 다른 새로운 React의 기능들과의 호환 가능성도 갖는다.
- 상태 정의는 증분 및 분산되므로 코드 분할이 가능하다.
- 상태를 사용하는 컴포넌트를 수정하지 않고도 상태를 파생된 데이터로 대체할 수 있다.
- 파생된 데이터를 사용하는 컴포넌트를 수정하지 않고도 파생된 데이터는 동기식과 비동기식 간에 이동할 수 있다.
- 우리는 탐색을 일급 개념으로 취급할 수 있고 심지어 링크에서 상태 전환을 인코딩할 수도 있다.
- 역호환성 방식으로 전체 애플리케이션 상태를 유지하는 것은 쉬우므로, 유지된 상태는 애플리케이션 변경에도 살아남을 수 있다.
설치
npm install recoil
or
yarn add recoil
주요개념
개요
Recoil을 사용하면 atoms (공유 상태)에서 selectors (순수 함수)를 거쳐 React 컴포넌트로 내려가는 data-flow graph를 만들 수 있다. Atoms는 컴포넌트가 구독할 수 있는 상태의 단위다. Selectors는 atoms 상태값을 동기 또는 비동기 방식을 통해 변환한다.
Atoms
Atoms는 상태의 단위이며, 업데이트와 구독이 가능하다. atom이 업데이트되면 각각의 구독된 컴포넌트는 새로운 값을 반영하여 다시 렌더링 된다. atoms는 런타임에서 생성될 수도 있다. Atoms는 React의 로컬 컴포넌트의 상태 대신 사용할 수 있다. 동일한 atom이 여러 컴포넌트에서 사용되는 경우 모든 컴포넌트는 상태를 공유한다.
const fontSizeState = atom({
key: 'fontSizeState',
default: 14,
});
Atoms는 디버깅, 지속성 및 모든 atoms의 map을 볼 수 있는 특정 고급 API에 사용되는 고유한 키가 필요하다. 두개의 atom이 같은 키를 갖는 것은 오류이기 때문에 키값은 전역적으로 고유하도록 해야한다. React 컴포넌트의 상태처럼 기본값도 가진다.
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>;
}
Selectors
Selector는 atoms나 다른 selectors를 입력으로 받아들이는 순수 함수(pure function)다. 상위의 atoms 또는 selectors가 업데이트되면 하위의 selector 함수도 다시 실행된다. 컴포넌트들은 selectors를 atoms처럼 구독할 수 있으며 selectors가 변경되면 컴포넌트들도 다시 렌더링된다.
const charCountState = selector({
key: 'charCountState', // unique ID (with respect to other atoms/selectors)
get: ({get}) => {
const text = get(textState);
return text.length;
},
});
우리는 useRecoilValue() 훅을 사용해서 charCountState 값을 읽을 수 있다.
function CharacterCount() {
const count = useRecoilValue(charCountState);
return <>Character Count: {count}</>;
}
Data Flow Graph
atoms(상태): 고유한 키를 가짐
|
selectors(순수함수): atoms이나 selectors를 입력으로 받음
|
components
Atoms(TodoList 샘플 만들기)
https://recoiljs.org/ko/docs/basic-tutorial/atoms
비동기 데이터 Fetch(Query)
https://recoiljs.org/ko/docs/guides/asynchronous-data-queries
정리
Simple ⇒ React의 한계 해소
주요 개념 ⇒ atoms / selectors
React Tree ⇒ Tree를 벗어난 3D shared state
Atoms ⇒ 공유되는 상태(get/set)
Selectors ⇒ 파생된 상태(get만 가능할수도..)
비동기 데이터 호출 ⇒ async / loadable
Async ⇒ Suspense / ErrorBoundary와 함께
useRecoilValueLoadable ⇒ .state / .contents
기타 ⇒ Atom Effects / family(매개변수 활용)
본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다
댓글