Why Recoil?

왜 Recoil을 사용할까?

우선 전역 상태관리는 개발을 하다보면 무조건 필요로 하게 된다. 특히나 전에 만들었던 프로젝트 경우에는 게임이였기 때문에, 더욱 필요했고, 이번에도 적지만 id 같은 경우에 모든 페이지마다 변경되는 state이다 보니 전역상태관리가 필요로 하게 된다.

recoil공식 설명에서는 사용하는 이유 즉 탄생배경을 다음과 같이 설명한다.

  1. 컴포넌트의 상태는 공통된 상위요소까지만 끌어 올릴 수 있어, 이 과정에서 거대한 트리가 다시 렌더링 되는 효과가 나온다.
  2. Context는 단일 값만 가질 수 있어, Consumer가 가지는 여러 값들의 집합을 담을 수 없다.
  3. 두 가지 특성이 트리의 상단부터 말단까지 이어져야 돼서 분할이 어려워진다.

즉 Recoil은 해당 문제를 해결하기 위해 orthogonal 하지만 본직적인 방향 그래프를 정의해서 React 트리에 붙이게 된다. 즉 그래프의 뿌리 (atoms) 으로부터 시작해 Selectors(순수함수)를 거쳐 컴포넌트로 흐르게 된다.

즉 Recoil의 사용함으로써 가져가는 장점은 다음과 같다.

  1. 동시성와 React의 호환성
  2. 상태정의 분산이 가능 -> 코드 분할이 쉽다
  3. 컴포넌트를 수정하지 않고, 파생된 데이터로 대체 가능
  4. 공유된 상태도 React local state로 간단하게 사용 가능

Atom

Recoil의 상태를 나타내는 상태 단위라 볼 수 있다.

Atom 생성

function atom<T>({
  key: string,
  default: T | Promise<T> | RecoilValue<T>,

  effects_UNSTABLE?: $ReadOnlyArray<AtomEffect<T>>,

  dangerouslyAllowMutability?: boolean,
}): RecoilState<T>

위와 유사하게, atom을 선언 해 주어야 atom 함수를 사용 할 수 있다.

  • key는 atom의 unique한 값
  • default는 초기값 혹은 selector, promise의 객체
  • effect_UNSTABLE는 Atom Effects 배열
  • dangerouslyAllowMutability는 atom이 변경될 경우, 등록된 컴포넌트에게 알리지 않고 리렌더링을 방지하는 옵션

Atom의 Hook

먼저 atom을 생성해야된다

const myState = atom({
  key: "uniqueKey",
  default: 0,
});

useRecoilState

atom을 읽고 쓰기 위해 사용

const [val, setVal] = useRecoilState(uniqueKey);

useRecoilValue

atom을 읽을 때 사용

const val = useRecoilValue(uniqueKey);

useSetRecoilState

atom에 쓰기 위해 사용 업데이트 할 수 있는 setter를 리턴한다 컴포넌트를 atom에 등록하지 않아, 변경이 되어도 리렌더링 되지는 않는다. -> 즉 atom을 사용하지 않는 경우 이 훅을 사용

const setVal = useSetRecoilState(uniqueKey);

useResetRecoilState

atom을 default를 초기화한다 비동기 setter를 리턴하며, 컴포넌트 리렌더링이 되지는 않는다

const reset = useResetRecoilState(uniqueKey);

useRecoilCallback

Recoil 상태에서 callback시킬 수 있는 훅

RecoilRoot

Atom 컨텍스트를 제공해주며, hook의 조상으로 사용된다.

override가 true라면 새로운 Scope 생성

import { RecoilRoot } from "recoil";

function App() {
  return (
    <RecoilRoot>
      <Components />
    </RecoilRoot>
  );
}

RecoilSelector

atom의 상태에서 파생된 데이터로, 상태에 의존하는 동적인 데이터이다.