Recoil을 오랜만에 쓸 때 보는 간단한 포스트

Ellie·2022년 5월 19일
7

Recoil

목록 보기
1/1
post-thumbnail

Recoil을 오랜만에 쓸 때를 대비하기 위한 간단한 포스트를 정리해봤다. 앞으로 Redux를 공부하고 써 볼 예정이기 때문이다. 나중에 다시 Recoil을 쓸 때 러닝 커브를 좀 더 줄여보기 위해 작성해보았다!

recoil에는 여러가지 훅이 있는데 이 훅들에 대해 먼저 정리해본다.


useRecoilValue

추천: 값만 사용할 때

const toDos = useRecoilValue(toDoState);

recoil atom에 저장한 state의 값을 반환한다.

state의 값만 반환하기 때문에 컴포넌트에서 상태를 읽어오기만 하면 될 때 사용하는 훅. 나중에 상태가 업데이트되면 리렌더링된다.


useSetRecoilState

추천: 값을 변경하기만 할 때

const setToDos = useSetRecoilState(toDoState);

// 업데이트 함수 작성
const addUser = () => {
  return setToDo(users => [...users, user])
}

recoil atom에 저장한 state의 값을 업데이트 하기 위한 setter함수를 반환한다.

상태를 변경하기 위해 비동기로 사용될 수 있는 setter함수를 리턴한다.
컴포넌트가 상태값을 가져오지 않고 쓰기(업데이트)만 하려고 할 때 사용한다. 컴포넌트가 값이 바뀔 때 리렌더링을 하기 위해 컴포넌트를 구독하지 않고도 값을 설정할 수 있게 해준다.


useRecoilState

추천: 값을 불러오고 변경하기도 해야할 때

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

recoil atom에 저장한 state의 값을 업데이트 하기 위한 setter함수를 반환한다.

react의 useEffect훅과 비슷하다. 해당 컴포넌트에서 값을 불러오고 변경하기도 해야할 때 사용한다. 앞서 useRecoilValueuseSetRecoilState를 합친 것이라고 보면 된다.


selector

추천: 같은 atom 상태 값으로 또다른 결과값을 얻고 싶을 때

const toDoSelector = selector({
  key: "toDoSelector",
  //get function필수
  get: ({ get }) => { //get함수는 option이라는 객체 인자가 필요하며 그 안의 들어있는 get이 필요하다.
    const toDos = get(toDoState) // toDos에 toDoState value을 할당할 수 있다. selector는 atom값에 접근 가능!
    return toDos.filter(toDo => toDo.category === "TO_DO"); // Array()- TO_DO 카테고리 배열, 다른 아웃풋이 나오게 된다.
  },
});

// 아래는 selector을 사용하는 컴포넌트
// selector을 사용하려면 useRecoilValue을 사용한다.
const toDos = useRecoilValue(toDoSelector);

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

selector을 이용하면 어떤 상태를 가져다가 다른 상태를 만들 수 있다. 굳이 새로운 atom을 만들지 않아도 하나의 atom에서 다르게 변형하여 사용할 수 있는 것이다.

다시 말하면, selector는 atom의 output을 변형시키는 도구다. 그러니까 같은 atom value로 setState와는 다른 값을 리턴할 수 있다. 주의해야 할 점은 순수함수여야 한다는 것이다.

또한 selector하나에 get함수를 이용하여 여러가지 atom상태값들을 전달받을 수 있다.


effects

추천: atom을 초기화 또는 동기화하려고 할 때

const toDoState = atom({
  key: "toDo",
  default: null,
  effects: [ // 로컬스토리지 저장 예시
    ({ setSelf, onSet }) => { // setSelf 함수는 초기값 지정. onSet함수는 값이 변경될 때마다 값을 동기화
      const todoStoreKey = "ToDo";
      const savedValue = localStorage.getItem(todoStoreKey);
      if (savedValue != null) {
        setSelf(JSON.parse(savedValue));
      }
      onSet((newValue, _, isReset) => {
        isReset
          ? localStorage.removeItem(todoStoreKey)
          : localStorage.setItem(todoStoreKey, JSON.stringify(newValue));
      });
    },
  ],
});
// setSelf 함수는 로컬스토리지에서 값을 불러와 초기값을 지정해주는 역할. 
// onSet 함수는 해당 atom값이 변경될 때마다 로컬스토리지와 atom 값을 동기화해주는 역할 

Recoil 공식문서: Atom Effect

Recoil에서 effects는 부수효과를 관리하고 atom을 초기화 또는 동기화하기 위한 API이다.
atom을 이용해 데이터베이스, 로컬 스토리지 등 다른 상태의 로컬 캐시 값을 사용하려면 effect를 사용해야 값이 변경될 때마다 업데이트할 수 있다.

Atom Effect의 어플리케이션

  • state synchronization(상태 동기화)
    atom을 원격 데이터베이스, 로컬 스토리지처럼 다른 상태의 로컬 캐시값으로 사용할 수 있다. 값이 변경될 때마다 해당 store을 구독하고 atom값을 업데이트할 수 있다.
    setSelf()는 그 값으로 atom을 초기화하며 초기 렌더링에 이용된다.

  • logging(로깅)
    특정 atom의 상태 변화를 간단히 기록할 수 있다.

    const currentUserIDState = atom({
      key: 'CurrentUserID',
      default: null,
      effects: [
        ({onSet}) => {
          onSet(newID => {
            console.debug("Current user ID:", newID);
          });
        },
      ],
    });

또한 Recoil effects 또한 cleanup의 부수효과를 관리하기 위해 선택적 cleanup핸들러를 리턴할 수도 있다.

const myState = atom({
  key: 'MyKey',
  default: null,
  effects: [
    () => {
      ...effect 1...
      return () => ...cleanup effect 1...;
    },
    () => { ...effect 2... },
  ],
});

마무리

나중에 recoil을 빠르게 쓰기 위해 정리해봤는데 역시 사람은 공부를 하면서 기록을 해야 한다는 것을 느낀다. 정리를 하니까 좀 더 recoil을 잘 이해하게 된 느낌이다. 뭔가 effects 개념에 대해서 어렴풋이 알고 쓰는 느낌이었는데, 이번에 100% 이해했다고 말할 순 없겠지만 setSelfonSet, trigger 등 주요 개념을 어떻게 사용하는지는 확실히 이해했다!

물론 Recoil은 지금 정리한 훅들과 API 이외에도 정말 유용한 것들이 많다. 하지만 당장 Recoil을 쓴다고 했을 때 정말 알고 있어야 하는 핵심 기능에 대해 정리해보았다. 또 더 알게 된 Recoil 지식이 있다면 틈틈히 정리하고 수정해야겠다!
그럼 이만 총총...

profile
정말로 아는 것인지 항상 의심하기

1개의 댓글

comment-user-thumbnail
2024년 10월 31일

useRecoilState 설명에서
"react의 useEffect훅과 비슷하다." 부분
useEffect 가 아니라 useState 아닌가요?

답글 달기