[React] Recoil - State Management

bomhada·2022년 4월 7일
0

📘 React study 

목록 보기
8/15
post-thumbnail

Recoil

React를 위한 상태 관리 라이브러리 입니다.

설치

명령어를 실행시켜주면 끝!

npm i recoil

사용하는 방법

RecoilRoot

recoil을 사용하는 컴포넌트는 부모 트리 어딘가에 RecoilRoot 컴포넌트를 가져와줘야합니다.
보통 App파일 안에 RecoilRoot를 가져옵니다.

import React from 'react';
import {RecoilRoot} from 'recoil';
import CreateCount from './CreateCount';

function App() {
  return(
    <RecoilRoot>
    	<CreateCount />
    </RecoilRoot>
  );
}

Atom.ts 생성

Atom과 typescript를 같이 쓸 경우 굳이 Atom파일 형식을 tsx로 하지 않아도 됩니다.
이유는 tsx파일 형식은 react+typescript를 사용할 시에 쓰이는데 이 곳에서는 typescript만 사용하기에 ts파일로 지정해서 사용하셔도 무관합니다.
Atom은 State의 단위이며, 상태(State)일부를 나타내는데, 컴포넌트들을 읽고 쓸 수 있습니다.
앞서 말한것 처럼 해당 atom의 값을 읽는 컴포넌들은 atom을 구독하는데, 만약 atom에 변화가 생기면 atom을 구독하는 모든 컴포넌트들이 리렌더링 됩니다.
atom 작성법은 아래와 같습니다.

import { atom } from "recoil";

export const counterState = atom({
  key: "counter",
  default: "",
}); 

Atom은 특별한 key값을 필요로하는데 중복이 되지 않도록 유의해야합니다.
생성한 atom을 사용하기 위해서는 useRecoilState()라는 훅을 사용합니다.

useRecoilState()

위와 같이 value와 변경 함수를 모두 얻고싶을 때 사용합니다.
useState와 비슷하게 쓰입니다.

const [value, modFn] = useSetRecoilValue(counterSelector);

⚠️ 가끔 사용하다보면 어떤것을 불러와야할지 이름이 헷갈릴 때가 있는데, 저는 그럴때는 Recoil을 빼고 읽어보면 구분하기 쉬워지더라구요ㅎㅎ..
use(Recoil)Value, useSet(Recoil)State는 useState를 사용할 때 배열을 네이밍을 떠올리면 되고, use(Recoil)State은 useState처럼 배열 값을 선언해야 사용할 수 있다고 떠올리니까 더이상 헷갈리지 않네요 :)

useRecoilValue()

atom으로부터 값을 불러올 때 사용합니다.

const value = useRecoilValue(counterSelector);

useSetRecoilState()

atom의 값을 변경할 때 씁니다.

const modFn = useSetRecoilValue(counterSelector);

selector()

기존의 state를 가져다가, 새로운 state를 만들 수 있고, 원하는 대로 변형이 가능합니다.
selector에는 get과 set 함수를 사용할 수 있습니다.
selector에서 값을 얻어오려면 state에서 값을 얻어올 때 쓰던 함수, 예를 들어, useRecoilValue 같은 것을 쓰면 됩니다.

get 함수는 selector가 어떤 것을 반환할지 결정하는 함수입니다.
그리고 인자로 객체를 받는데 원하는 atom을 가져올 수 있고, 여러개의 atom을 가져올 수 있습니다.

set 함수는 Recoil 상태의 값을 설정할 때 사용되고, 두개의 매개 변수를 가집니다.
첫 번째 매개변수는 recoil state, 두 번째 매개변수는 새로운 값(newValue)입니다.

selector 예제

selector를 이용해 분 -> 시간, 시간 -> 분으로 계산해주는 코드 입니다.

MinutesToHours.tsx

import { useRecoilState } from "recoil";
import { hourSelector, minuteState } from "./Atom";

export function MinutesToHours() {
  const [minutes, setMinutes] = useRecoilState(minuteState);
  const [hours, setHours] = useRecoilState(HourSelector);
  const onChangeMinutes = (event:React.FormEvent<HTMLInputElement>) => {
    setMinutes(+event.currentTarget.value);
  };
  const onChangeHours = (event:React.FormEvent<HTMLInputElement>) => {
    setHours(+event.currentTarget.value);
  };
  
  return(
  <>
    <input
      value={minutes}
      onChange={onChangeMinutes}
      type="number"
      placeholder="Minutes"
    />
    <input
      value={minutes}
      onChange={onChangeHours}
      type="number"
      placeholder="Hours"
    />
  </>
  );
}

Atom.ts

import { atom, selector } from "recoil";

export const minuteState = atom({
  key: "minutes",
  default: 0,
});

export const hourSelector = selector({
  key: "hours",
  get: ({get}) => {
    const minutes = get(minuteState);
    return minutes / 60;
  },
  set: ({set}, newValue) => {
    const minutes = Number(newValue) * 60;
    set(minuteState, minutes);
  }
});

0개의 댓글