[Recoil] 리코일 사용

mj·2021년 7월 27일
0

What is Recoil?

recoil은 react의 상태관리 라이브러리이다.
react는 자체로 상태관리를 할 수 있다. 하지만 컴포넌트의 상태가 공통된 상위 요소까지 끌어올림으로 공유하면서 대규모의 트리가 렌더링될 수 있기 때문에 효과적이지 않다.
Context를 사용해도 단일 값만 저장할수 있고 자체 Consumer를 가지는 여러 값들의 집합을 담을 수는 없다.
recoil의 공식문서에는 이렇게 적혀있다.

우리는 공유상태(shared state)도 React의 내부상태(local state)처럼 간단한 get/set 인터페이스로 사용할 수 있도록 boilerplate-free API를 제공한다. (필요한 경우 reducers 등으로 캡슐화할 수도 있다.)
우리는 동시성 모드(Concurrent Mode)를 비롯한 다른 새로운 React의 기능들과의 호환 가능성도 갖는다.
상태 정의는 증분 및 분산되므로 코드 분할이 가능하다.
상태를 사용하는 컴포넌트를 수정하지 않고도 상태를 파생된 데이터로 대체할 수 있다.
파생된 데이터를 사용하는 컴포넌트를 수정하지 않고도 파생된 데이터는 동기식과 비동기식 간에 이동할 수 있다.
우리는 탐색을 일급 개념으로 취급할 수 있고 심지어 링크에서 상태 전환을 인코딩할 수도 있다.
역호환성 방식으로 전체 애플리케이션 상태를 유지하는 것은 쉬우므로, 유지된 상태는 애플리케이션 변경에도 살아남을 수 있다.

지금은 이 내용을 이해하지 않아도 좋다. 주요개념들을 요약하면서 이해하자!

주요개념 요약

Atoms

Atoms는 상태의 단위이다. update와 subscribe도 가능하다. atom이 update되면 각각의 subscribe component는 다시 rendering한다! 동일한 atom이 여러 컴포넌트에서 사용되면 해당 상태를 공유한다.

const fontSizeState = atom({
  key: 'fontSizeState',
  default: 14,
})

atom은 디버깅과 지속성을 위해, 그리고 모든 atoms의 map을 볼 수 있는 특정 고급 API에 사용되는 key가 필요하고 이 값은 고유해야 한다. 기본값인 default도 가질 수 있다.

component에서 atom을 읽고 쓰려면 useRecoilState라는 hook을 사용한다.
react의 useState와 흡사하지만, 컴포넌트간에 공유가 될 수 있다는 차이가 있다!

const FontButton = () => {
  const [ fontSize, setFontSize ] = useRecoilState(fontSizeState);
  return(
    <button onClick={() => setFontSize((size) => size + 1)} style={fontSize}>
    	Click To This Button!
    </button>
  )
}

Selectors

Selectors는 atoms나 다른 selectors를 입력으로 받아들이는 순수 함수이다. 상위의 atoms 또는 selectors가 업데이트되면 하위의 selector 함수도 다시 실행된다. 컴포넌트들은 selectors를 atoms처럼 구독할 수 있으며 selectors가 변경되면 컴포넌트들도 다시 렌더링된다.

Selectors는 상태를 기반으로 하는 파생 데이터를 계산하는 데 사용된다. 최소한의 상태 집합만 atoms에 저장하고 다른 모든 파생되는 데이터는 selectors에 명시한 함수를 통해 효율적으로 계산함으로써 쓸모없는 상태의 보존을 방지한다.

Selectors는 어떤 컴포넌트가 자신을 필요로하는지, 또 자신은 어떤 상태에 의존하는지를 추적하기 때문에 이러한 함수적인 접근방식을 매우 효율적으로 만든다.

컴포넌트의 관점에서 보면 selectors와 atoms는 동일한 인터페이스를 가지므로 서로 대체할 수 있다.

const fontSizeLabelState = selector({
  key: 'fontSizeLabelState',
  get: ({get}) => {
    const fontSize = get(fontSizeState);
    const unit = 'px';

    return `${fontSize}${unit}`;
  },
});

get 속성은 계산될 함수다. 전달되는 get 인자를 통해 atoms와 다른 selectors에 접근할 수 있다. 다른 atoms나 selectors에 접근하면 자동으로 종속 관계가 생성되므로, 참조했던 다른 atoms나 selectors가 업데이트되면 이 함수도 다시 실행된다.

Selectors는 useRecoilValue()를 사용해 읽을 수 있다. useRecoilValue()는 하나의 atom이나 selector를 인자로 받아 대응하는 값을 반환한다.

function FontButton() {
  const [ fontSize, setFontSize ] = useRecoilState(fontSizeState);
  //useRecoilVaule로 fontSizeLabelState selector를 읽어올 수 있다.
  const fontSizeLabel = useRecoilValue(fontSizeLabelState);
  
  return(
    <>
      <div>Current font size: ${fontSizeLabel}</div>
      <button onClick={setFontSize(fontSize + 1)} style={{fontSize}}>
        Click to This Buton!
      </button>
    </>
  )
}

이제는 Recoil을 사용하여 상태관리를 위해 자원을 낭비하지 않아도 된다!

0개의 댓글