TIL93. Recoil

jo_love·2021년 12월 29일
0
post-thumbnail

또 다른 상태관리 라이브러리 'Recoil'에 대해서 알아보자.

Recoil?

페이스북에서 만든 상태 관리 라이브러리이다. 대표적인 상태관리 라이브러리 'redux'는 react만을 위한 상태관리 도구가 아니기에 react에 최적화되지도 않았고, 러닝커브도 높았다. 이에 비해 recoil은 hook을 써봤다면 쉽게 사용할 수 있는 수준이다.

Recoil 사용하기

...
import { RecoilRoot } from 'recoil';

ReactDOM.render(
  <React.StrictMode>
    <RecoilRoot>
        <App />
    </RecoilRoot>
  </React.StrictMode>,
  document.getElementById('root'),
);

전역에서 사용할 수 있도록 root에 recoilRoot 감싸주기

atom

// atom.ts
import { atom } from "recoil";

export const isDarkAtom = atom({
  key: 'isDark', // 식별자 역할
  default: false, // 초기값
});

기존의 상태관리 라이브러리에서 쓰이는 store와 유사한 개념으로, 상태의 단위를 말한다.
atom의 상태가 업데이트되면, atom을 구독하고 있던 모든 컴포넌트들의 state가 새로운 값으로 리렌더링된다.

useRecoilValue

mport { useRecoilValue } from 'recoil';
import { isDarkAtom } from './atoms';

function App() {
  const isDark = useRecoilValue(isDarkAtom); //atom 값 받아오기
  return (
    <>
      <ThemeProvider theme={isDark ? darkTheme : lightTheme}>
        <GlobalStyle />
        <Router />
      </ThemeProvider>
    </>
  );
}

컴포넌트와 atom을 연결하기 위한 도구

useSetRecoilState

// child.js
import { useSetRecoilState } from 'recoil';

const setDarkAtom = useSetRecoilState(isDarkAtom);
  const toggleMode = () => {
    setDarkAtom((val) => !val);
  };

vaule를 수정할 수 있는 함수로, setState와 같은 방식으로 작동한다.

useRecoilState

import { useRecoilState } from 'recoil';

  const [isDark, setIsDark] = useRecoilState(isDarkAtom);

상태를 가져오거나 변경하는 행동, 둘 다 하고 싶을 때 사용한다.
즉, useRecoilValue + useSetRecoilState

  • selector값도 사용가능하다.

selector

recoil에서 파생된 상태로 selector는 순수함수여야한다.

  • get RecoilValueReadOnly

// A input에 'minute'을 입력하면 B input창에 'hour'로 바꿔주는 경우
export const minuteState = atom({
  key: 'minutes',
  default: 0,
});

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

get프로퍼티를 통해 원래의 state를 가공하여 반환한다. read-only 한 selector는 의존성을 기준으로 의존성 중 어떠한 것이 업데이트 되면 selector는 다시 평가된다.

  • set writeable

// 반대로 B input창에 'hour'을 입력하면 A input창에서 'minute'으로 바꿔주는 경우 
export const minuteState = atom({
  key: 'minutes',
  default: 0,
});

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함수의 2가지 인자: 수정하고 싶은 recoil atom, 새로운 값
    set(minuteState, minutes);
  },
});

// useRecoilState - selector
const [minutes, setMinutes] = useRecoilState(minuteState);
//  array의 첫번째 요소는 위 selector의 get함수의 값, 두번째 요소는 set property를 실행시키는 함수
const [hours, setHours] = useRecoilState(hourSelector);

hourSelector 에서 minuteState를 변경하도록 만들었기에 두 곳에서 모두 값을 설정할 수 있게 되었다. 두 개의 atom을 각각 만드는 대신, 2개의 속성을 가지는 selector를 사용해서 atom의 값을 set하도록 만들 수 있다.

profile
Lv.1🌷

0개의 댓글