Tech/상태관리

[Recoil] atomFamily로 여러개의 atom 관리하기

닝닝깅 2023. 8. 5. 17:12

개요

영화 웹 서비스 프로젝트를 진행하던 중 각 슬라이더를 구독하는 개별적인 atom이 필요했다.

동일한 속성의 atom을 하나하나 생성하는 것이 비효율적이라고 생각했고, 다른 방법을 찾아보던 중 recoil에서 제공하는 atomFamily API를 알게 되었다.

 

AtomFamily : 동일한 형태의 atom을 생성하는 팩토리 함수 리턴

atomfamily를 활용하면 특정 파라미터에 따른 독립적인 atom state를 생성할 수 있다.

이때 사용되는 특정 파라미터를 key라고 하겠다.

 

예를 들어 Todo 리스트의 개별적인 todo의 상태를 구독하는 atom을 만들고 싶다고 해보자. 

 

atomFamily는 다음과 같이 작성된다. 여기서 key 값은 id가 된다.

const todoItemState = atomFamily<ITodo, ITodoID>({
  key: 'todoItemState',
  default: (id) => {
    return {
      id,
      title: '',
      isDone: false,
    };
  },
});

 

atomFamily의 타입 정의는 다음과 같다.

ITodo - 생성될 atom의 타입

ITodoID - atomFamily 호출 시 파라미터로 전달되는 id 값의 타입

 

default 영역에는 atom의 초기값을 설정해준다.

이때 id 값을 받는 함수를 default 값으로 설정하여 각 atom의 default 값을 독립적으로 설정할 수 있다.

 

완성된 팩토리 함수를 호출할 때는 key를 사용하여 다음과 같이 atom을 생성한다.

const [todo, setTodo] = useRecoilState(todoItemState("one"))

 

AtomFamily로 생성된 key 관리

atomFamily와 key를 통해 atom을 무한대로 생성하다보면 얼마나 많은 key 값이 있는 지 모를 수 있다.

만약 특정 작업을 통해 atom을 한번에 통제할 때가 필요한 경우에 이는 문제가 될 수 있기 때문에 별도의 관리가 필요하다.

 

그래서 key 관리를 위한 atom을 따로 생성했다.

위의 예시에서 확장하여 TodoID를 관리하는 atom을 생성한다고 해보겠다.

const todoIdsState = atom<string[]>({
  key: 'todoIdsState',
  default: [],
});

 

 

이때 id를 활용하여 새로운 Todo를 만들 때마다 해당 id를 위에서 생성한 atom에 추가하여야 한다.

//1. atomFamily로 Atom 생성
const [todo, setTodo] = useRecoilState(todoItemState("one"))

//2. 생성한 Atom의 key를 key 관리값에 추가하기
const setTodoIdsState = useSetRecoilState(todoIdsState)
setTodoIdsState((prev) => [...prev, "one"])

 

이와 비슷한 selectorFamily도 있다는데 더 알아봐야지


Ref

https://recoiljs.org/ko/docs/api-reference/utils/atomFamily/

https://junglast.com/blog/recoil-atomfamily-atom