프로그래밍/React

[Recoil] 리코일 이해하기

라다디 2022. 9. 15. 02:07

 

Recoil

리코일은 리액트에서 사용할 수 있는 전역 상태 관리 라이브러리이다. 

여기서 전역 상태(global state)란 어플리케이션 전체에서 공유되는 state를 의미한다.

 

동기 | Recoil

호환성 및 단순함을 이유로 외부의 글로벌 상태관리 라이브러리보다는 React 자체에 내장된 상태 관리 기능을 사용하는 것이 가장 좋다.

recoiljs.org

리코일의 필요성은 위의 공식 문서에서 확인할 수 있다.

간단하게 props drilling으로 인한 불필요한 리렌더링 발생을 방지하고 유지보수의 어려움을 해결하기 위함으로 이해했다. 

 

Recoil은 다음 명령어로 설치할 수 있다.

npm install recoil

 

Atoms

 

atom(options) | Recoil

atom은 Recoil의 상태를 표현한다. atom() 함수는 쓰기 가능한 RecoilState 객체를 반환한다.

recoiljs.org

atom은 컴포넌트가 구독할 수 있는 state의 일부를 의미한다.

어떤 컴포넌트에서나 읽고 쓸 수 있으며 atom의 값을 읽는 컴포넌트들은 암묵적으로 atom을 구독한다. 

그래서 atom에 어떤 변화가 있으면 해당 atom을 구독하는 모든 컴포넌트들이 리렌더링 된다. 

 

recoil 상태를 사용하는 컴포넌트는 부모 트리 어딘가에 나타나는 RecoilRoot가 필요하다.

index.tsx 파일에 넣어줬다.

 

src 폴더 밑에 atoms.ts 파일을 만들고 다음과 같이 작성하였다.

atom은 키와 기본값을 요구한다. 

두개의 atom이 같은 키를 갖는 것은 오류이기 때문에 atom의 키값은 전역적으로 고유해야 한다. 

 

컴포넌트와 atom을 연결하고 값을 가져오기 위해서는 useRecoilValue 훅을 사용한다. 

const isDark = useRecoilValue(isDarkAtom)

이렇게 하면 컴포넌트가 isDarkAtom과 연결되고, isDark의 값은 false가 된다. 

 

그렇다면 atom의 값은 어떻게 수정해야 할까?

atom의 값을 수정하기 위해서는 useSetRecoilState 훅을 사용한다. 

const setterFn = useSetRecoilState(isDarkAtom);

이렇게 하면 state의 값을 업데이트하기 위한 setter 함수를 받을 수 있다. 

 

useRecoilValue와 useSetRecoilState를 쓰는 것 외에 useRecoilState를 사용하는 방식도 있다.

useRecoilState 훅은 state의 값과 setter 함수를 반환한다. 

const [toDos, settoDos] = useRecoilState(toDoState);

 

[정리]

useRecoilValue: state값을 리턴

useSetRecoilState: setter 함수를 리턴

useRecoilState: state, setter 함수를 모두 리턴

 

Selector

 

selector(options) | Recoil

Selector는 Recoil에서 함수나 파생된 상태를 나타낸다. 주어진 종속성 값 집합에 대해 항상 동일한 값을 반환하는 부작용이 없는 "순수함수"라고 생각하면 된다. get 함수만 제공되면 Selector는 읽기

recoiljs.org

selector는 atom이나 다른 selector를 기반으로 파생된 state를 만드는 순수 함수이다. 

참고로 순수 함수란 같은 입력에 대해 항상 같은 출력값을 가지는 함수를 의미한다.

기존 state를 가져온 뒤 이를 이용해 새로운 state(derived state)를 만들어 반환할 수 있다.

export const hourSelector = selector<number>({
  key: "hours",
  get: ({ get }) => {
    const minutes = get(minuteState);
    return minutes / 60;
  },
});

selector에는 고유한 key 값이 필요하며, get 함수를 통해 derived state를 반환하며 이 값이 hourSelector의 값이 된다.

참조했던 atoms나 selector가 업데이트되면 get 함수도 다시 실행된다.  

selector에 get 함수만 제공되면 read-only의 RecoilValueReadOnly 객체를 반환한다. 

selector의 값을 읽을 때는 useRecoilValue를 사용한다. 

const hours = useRecoilValue(hourSelector);

 

selector에는 한 가지 속성이 더 있는데 바로 set 속성이다.

set 속성은 atom을 수정하는 것을 도와준다. 

selector에 set 함수 또한 제공되면 writable한 RecoilState 객체를 반환한다.

export const hourSelector = selector<number>({
  key: "hours",
  get: ({ get }) => {
    const minutes = get(minuteState);
    return minutes / 60;
  },
  set: ({ set }, newValue) => {
    const minutes = Number(newValue) * 60;
    set(minuteState, minutes);
  },
});

set 함수는 두 개의 인자를 가지는데 첫 번째 인자는 수정하고자 하는 atom이고, 두번째 인자는 새로운 값이다. 

const [hours, setHours] = useRecoilState(hourSelector);

위의 useRecoilState는 setHours라는 state를 변경할 수 있는 set 함수도 반환하고 있다.

이는 writable한 state, 즉 atom의 값만 수정할 수 있는 것이다.

selector의 값을 수정하는 함수가 아니다.

 


공식 문서와 아래 블로그의 포스팅, 노마드 코더의 React JS 마스터 클래스 강의를 참고하여 정리하였습니다.