React/유용한 NPM

[React]Recoil 간단한 예제 코드

DevStory 2021. 7. 25.

Recoil 라이브러리의 필요성

지난 포스팅에서는 자식 컴포넌트가 부모 컴포넌트의 state를 변경하는 방법에 대해 알아보았습니다.

그리고 부모 컴포넌트의 state가 변경되면서 부모 컴포넌트에 속하는 모든 자식 컴포넌트들이 re-render 되는 것도 알게 되었습니다.

 

Recoil 라이브러리는 모든 자식 컴포넌트들이 re-render 되는 것을 방지하기 위해 탄생한 상태 관리 라이브러리입니다.

부모 컴포넌트의 state를 공유하지 않고 Atoms이라는 저장소에 상태를 관리합니다. 컴포넌트들은 Atoms에 접근하여 상태를 공유하기 때문에 상태를 공유하기 위해서 더 이상 부모 컴포넌트의 state에 의존하지 않아도 됩니다.

 

Recoil 라이브러리의 자세한 내용 및 사용 방법은 아래 공식 문서를 참고 부탁드리겠습니다.

 

공식 문서

https://recoiljs.org/ko/

 

https://recoiljs.org/ko/

A state management library for React.

recoiljs.org


상태 관리 라이브러리를 사용하지 않았을 경우 문제점

ButtonComponent 컴포넌트가 App 컴포넌트의 state를 변경하면서 App의 자식 컴포넌트들이 모두 re-render 되었습니다.

App의 자식 컴포넌트
→ View, NotWork, ButtonComponent

Recoil 라이브러리를 사용하여 NotWork 컴포넌트는 re-render 되지 않도록 처리합니다.


Atom

Atom은 컴포넌트에서 상태를 공유할 수 있는 단위입니다. 값을 변경할 수도 있으며, 구독도 할 수 있습니다. 구독은 유튜브, 블로그의 구독과 동일한 의미로 컴포넌트는 Atom을 구독할 수 있습니다. 동일한 Atom이 여러 컴포넌트에서 사용되는 경우에는 컴포넌트들은 Atom을 통해 상태를 공유합니다. 

const dataState = atom({
  key: "dataState",
  default: data
});

atom 함수를 사용하여 전역적으로 고유한 key와 기본 값인 default를 지정합니다. 

export function ButtonComponent() {
  const [data, setData] = useRecoilState(dataState);

  const handleButtonClick = () => {
    const newList = [
      ...data,
      {
        Book: "TEST"
      }
    ];
    setData(newList);
  };

  return (
    <div>
      <button type="button" onClick={handleButtonClick}>
        부모 컴포넌트의 state를 변경합니다.
      </button>
    </div>
  );
}

컴포넌트에서 atom을 읽고 변경하기 위해서는 useRecoilState라는 hook을 사용합니다. useState와 비슷하지만 상태는 다른 컴포넌트들에게 공유가 된다는 차이가 있습니다.


Selector

Atoms에 저장된 상태들을 가공하여 가져오거나 가공하여 저장하고 싶을 경우 사용합니다. select 함수를 사용하여 key와 get, set을 작성합니다. get은 필수지만, set는 생략 가능합니다.

const getDataState = selector({
  key: "getDataState",
  get: ({ get }) => {
    return get(dataState);
  }
});

Selectors는 useRecoilValue()를 사용하여 읽을 수 있으며, atom 또는 selector를 인자로 받아 대응하는 값을 반환합니다.

export function View() {
  const getData = useRecoilValue(getDataState);

  console.log(`View Component 호출`);
  return (
    <div>
      <ul>
        {getData.map((value, index) => (
          <li key={index}>Book : {value.Book}</li>
        ))}
      </ul>
    </div>
  );
}

컴포넌트 재설계

Recoil 라이브러리를 사용하여 상태를 Atoms에 관리합니다.

ButtonComponent 컴포넌트에서 버튼을 클릭하여 상태를 변경하고 View 컴포넌트는 selector을 사용하여 변경된 상태를 읽을 수 있도록 합니다. 

 

더 이상 NotWork 컴포넌트는 re-render 되지 않으며, Atoms에 관리되고 있는 상태가 변경되었을 경우 ButtonComponent 컴포넌트와 View 컴포넌트만 렌더링 됩니다.


샘플

※ 화면 처음 실행 시 View 컴포넌트와 ButtonCompoent가 2번 렌더링 되는 문제가 있습니다. StackOverFlow와 Reddit에서 검색했을 때, <StrictMode>...<StrictMode>가 원인이라고 하는데, <StrictMode>...<StrictMode>가 없어도 2번 렌더링 되었습니다. 원인에 대해서는 좀 더 분석을 하도록 하겠습니다.


마무리

Recoil 라이브러리의 기본적인 개념과 사용법만 적용하였기에 코드를 작성하였고 내용을 작성했기에 부족한 점이 많습니다. Recoil 라이브러리는 불안정한 라이브러리라고 평가를 받고 있지만, Redux를 사용하다가 Recoil을 사용해보니 장점밖에 없어 보이는 라이브러리라고 생각이 됩니다.

 

개인적으로 Redux를 이해하는 것도 어렵고 코드를 작성하는 것도 어려웠다 보니 의도하지 않게 Recoil을 찬양하는 글을 작성하게 되었습니다. 다음에는 Recoil에 대해 좀 더 구체적으로 공부하여 정리하도록 하겠습니다.

반응형

댓글