Recoil에 대해 알아보기

oweaj·2023년 5월 30일
0

React 상태관리 라이브러리인 recoil에 대해 정리를 해보려고한다.

상태관리가 필요한 이유?

React는 state에 변동이 생기면 리렌더링이 되어 페이지에 변동이 생기는데 이 state을 전달하려면 부모 컴포넌트에서 자식 컴포넌트로만 가능하다. 예를들어 A부터 Z까지 알파벳 컴포넌트가 있다고 가정하고 A라는 컴포넌트의 state를 Z라는 자식 컴포넌트가 쓰고싶다면 A~Z사이에 있는 모든 컴포넌트는 A컴포넌트의 state가 필요없어도 Props로 전달해 줘야 한다. 이 부분이 Props drilling 이라고한다. Props drilling으로 인한 불필요한 리렌더링 발생을 방지하고 유지보수의 어려움을 해결하기 위해 상태관리가 필요하다.

recoil 특징

  • React 전용 상태 관리 라이브러리이기 때문에 React처럼 작동을 하며 쉽게 접근할 수 있어 React 문법 친화적이다.

  • store, action, reducer 등 여러 가지를 신경 쓸 일 없이 초기 세팅이 직관적이고 간단하다.

  • 추가 라이브러리 없이 비동기 처리를 간단하게 할 수 있다.

  • 내부적으로 자동적 캐싱되어 빠르다.


시작하기

// 설치
npm install recoil
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { BrowserRouter } from "react-router-dom";
import { RecoilRoot } from "recoil";

const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
root.render(
  <RecoilRoot>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </RecoilRoot>
);

최상단의 App 컴포넌트를 RecoilRoot로 감싸주면 전역으로 상태관리 할 수 있도록 해준다.

Atoms

Atom은 Recoil 상태의 단위를 의미하고 업데이트와 참조가 가능하며 key, default 2개의 프로퍼티를 필수로 설정해야한다.

export const numberState = atom({
  key: "numberState",
  default: 0,
});
  • key : 고유한 키 값.
  • default : atom의 초기값을 정의.

해당 Atom을 컴포넌트에서 사용하려면 Recoil에서 제공하는 hooks을 사용해야 한다.

  • useRecoilValue() : 전역 상태의 값을 참조하기위해 사용되고 변수를 할당해 사용한다.
const number = useRecoilValue(numberState)
  • useSetRecoilState() : setter 역할을 하므로 atom을 변경 시킬 수 있고 변수를 할당해 사용한다.
const setNumber = useSetRecoilState(numberState)
  • useRecoilState() : 전역 상태의 값을 참조할 수 있고 변경 시킬 수도 있다.
const [number, setNumber] = useRecoilState(numberState) // useState와 유사
  • useResetRecoilState() : 전역 상태를 초기값으로 reset하기 위해 사용된다.
const resetNumber = useResetRecoilState(numberState)

selectors

selector는 파생된 상태의 일부를 나타낸다. 즉 선언된 atom을 처리해 새로운 값을 return 하거나 값을 변경하는 역할을 하는데 사용된다.

export const numberSelector = selector({
  key: "numberSelector",
  get: ({ get }) => {
    const result = get(numberState) / 1.61;
    return result.toFixed(2);
  },
  set: ({ set }, newNumber) => set(numberState, (newNumber * 1.61).toFixed(2)),
});
  • get : 파생된 상태의 값을 평가하는 함수.
  • set : selector는 쓰기 가능한 상태를 반환.

selector로 간단하게 km와 mile 단위를 변환하면서 적용시켜보았다.
(1mile = 1.609344km로 기준을 쉽게 1.61km로 잡고 소수점 자릿수 2자리로 지정)

// App.js
function App() {
  return (
    <div className="absolute modalPosition flex flex-col gap-4">
      <Atest />
      <Btest />
    </div>
  );
}
// Atest.js
import React, { useState, useEffect } from "react";
import { useRecoilState } from "recoil";
import { numberState } from "Atom/atom";

const Atest = () => {
  const [stateNum, setStateNum] = useRecoilState(numberState);
  const [value, setValue] = useState("");

  useEffect(() => {
    setValue(stateNum);
  }, [stateNum]);

  return (
    <div className="flex gap-4">
      <input className="w-40 h-10 border border-black px-2" onChange={(e) => setValue(e.target.value)} value={value}></input>
      <button type="button" className="w-12 h-10 border border-black" onClick={() => setStateNum(+value)}>
        km
      </button>
    </div>
  );
};

export default Atest;
//Btest.js
import React, { useState, useEffect } from "react";
import { useRecoilState } from "recoil";
import { numberSelector } from "Atom/atom";

const Btest = () => {
  const [selectorNum, setSelectorNum] = useRecoilState(numberSelector);
  const [value, setValue] = useState("");

  useEffect(() => {
    setValue(selectorNum);
  }, [selectorNum]);

  return (
    <div className="flex gap-4">
      <input className="w-40 h-10 border border-black px-2" onChange={(e) => setValue(e.target.value)} value={value}></input>
      <button type="button" className="w-12 h-10 border border-black" onClick={() => setSelectorNum(+value)}>
        mile
      </button>
    </div>
  );
};

export default Btest;


🖇️ Reference

profile
데굴데굴데굴데굴데굴

0개의 댓글