본문 바로가기
부트캠프교육중/react

[React] Recoil 정리

by 뭉지야 2023. 9. 5.
728x90

Recoil은 Facebook에서 만든 React전용 상태 관리 라이브러리입니다.

상태관리 툴을 사용하면 state값들을 props로 계속 타고들어가지 않아도 되어 코드가 깔끔해집니다.
프로젝트의 규모가 커질수록 상태 관리 또한 필요성이 커지게 됩니다.
대표적인 상태관리툴로는 Redux, Mobx 등이 있습니다.

 


먼저 Recoil 패키지 설치합니다.

npm install recoil

recoil을 사용하기 위해서는 사용하고자하는 부모 컴포넌트에다 <RecoilRoot>를 사용해야 합니다.

(Recoil 초기연동할때 사용됩니다.)

리코일로 전역상태를 관리할 범위를 RecoilRoot 컴포넌트로 감싸줍니다.
RecoilRoot는 리덕스나 컨텍스트의 Provider와 같은 역할을 합니다.

 

index.tsx


import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { RecoilRoot } from 'recoil';


const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <RecoilRoot>     
    <App />
    </RecoilRoot>
  </React.StrictMode>
);

atom

atom은 redux의 store와 같은 개념입니다.
말그래도 저장소입니다.

리코일에서는 기본적으로 상태를 아톰(atom)이라는 단위로 관리합니다.
atom은 key와 default값을 설정해주어야합니다.

key
- atom을 식별하는데 필요한 고유한 문자열입니다.

default
- 초기값을 설정해주어야합니다.

 

import { atom }  from "recoil";

export const toDoState = atom({
  key: "countState",
  default: 0,
});

0을 기본값으로 갖는 countState 라는 전역상태(아톰)가 새로 만들어진 모습입니다.

 

생성한 아톰은 컴포넌트에서 다음과 같이 불러와 사용할 수 있습니다.

import React from "react";
import { useRecoilState } from "recoil";
import { countState } from "../store/counter";

const ControlNumber = () => {
  const [count, setCount] = useRecoilState(countState);
  
  const increase = () => {
    setCount(count + 1);
  };

  const decrease = () => {
    setCount(count - 1);
  };
  return (
    <div>
      <button onClick={increase}>+</button>
      <button onClick={decrease}>-</button>
    </div>
  );
};

export default ControlNumber;


useRecoilState() 훅을 통해 방금 정의한 counterState 아톰을 사용합니다.
보시면 useState 구문을 사용할 때와 매우 유사함을 알 수 있습니다!


atom Hook

 

-atom으로 정의된 상태를 컴포넌트에서 Hook을 이용하여 사용한다.

-useRecoilValue : value를 가져오는거, atom의 상태만 가져온다.
-useSetRecoilState : value를 수정하는거

 


Selector

 

-selector는 atom(state)를 기반으로 파생된 데이터를 만들어내는데 사용된다.

-atom의 상태에서 파생된 데이터, 즉 atom의 상태에 의존하는 동적인 데이터를 의미
주어진 atom의 상태에 대해 항상 동일한 값을 반환하는 순수함수

Selector를 사용하는이유?
-최소한의 state만 atom에 저장하고 다른 모든 파생되는 데이터는 selector의 함수를 통해 효율적으로 계산함으로써 쓸모없는 상태의 보존을 방지할 수 있다.

 

-key: atom의 key와 동일하며, 고유한 문자열을 가져야한다.

 

-get: get은 파생된 상태의 값을 평가하는 함수로, 매개변수로 콜백객체를 받는데, 콜백 객체 내의 get 메소드를 이용하여 다른 atom이나 selector를 가져온다.

 

-set: set 속성이 설정되면 selector는 쓰기 가능한 상태가 된다. set은 콜백객체와 새로운 값 2가지를 매개변수로 받는데, 콜백 객체 내의 set 메소드를 이용하여 다른 atom의 값을 새로운 값으로 변경시킨다.

 

-get만 있는 selector의 경우 useRecoilValue를 사용해도 무방하다.
get과 set이 둘다 있는 selector를 사용하기 위해서는 useRecoilState를 사용한다. 

export const toDoSelector = selector({
  key: "toDoSelector",
  get: ({ get }) => {
     const toDos = get(toDoState);
     return [toDos.filter((toDo)=> toDo.category === "TO_DO")];
},
})

이렇게 get으로 atom을 가져와서 변형해서 return 하는게 selector이다.


set

set은 state를 set하는 것을 도와주는 속성이다.
atom을 수정하는걸 도와준다.

set함수는 원하는 state가 어떤 것이던지 그걸로 수정하게끔 해준다.

두번째 argument는 우리가 보내는 새로운 값을 주고있다.

const [hours, setHours] = useRecoilState(hourSelector);

여기에서 첫번째 argument, 즉 array의 첫번째 요소는 get property로부터 return 한 값이다.
두번째 요소는 set property를 부르는 함수가 된다.

 

atom이나 selector로 useRecoilState를 쓸때 결과 array의 첫번째 item은 atom의 값이거나 selector의 get함수의 값이다.
array의 두번째 요소는 atom을 수정하는 함수이거나 selector의 set property를 실행시키는 함수이다.


atoms.tsx


import { atom, selector } from "recoil";

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

export const hourSelector = selector({
  key: "hours",
  get: ({ get }) => {
    const minutes = get(minutesState);
    return minutes / 60;
  },
});
import React from "react";
import { useRecoilState, useRecoilValue } from "recoil";
import { minutesState, hourSelector } from "./atoms";

function App() {
  const [minutes, setMinutes] = useRecoilState(minutesState);
  const hours = useRecoilValue(hourSelector);
  const onMinutesChange = (event: React.FormEvent<HTMLInputElement>) => {
    setMinutes(+event.currentTarget.value);
  };
  return (
    <>
      <GlobalStyle />
      <input
        value={minutes}
        onChange={onMinutesChange}
        type="number"
        placeholder="Minutes"
      />
      <input value={hours} type="number" placeholder="Hours" />
    </>
  );
}

export default App;

이정도만 일단 정리하고 

selector에서 비동기와 관련된 부분이 있는거 같은데 

더 공부하고 해봐야할거같다.

728x90