Home [React] Recoil 사용하기
Post
Cancel

[React] Recoil 사용하기


Recoil 사용하기

Recoil은 Facebook에서 개발한 오픈소스 상태 관리 라이브러리로, React 애플리케이션에서 상태를 효율적으로 관리할 수 있도록 도와줍니다.

설치

1
2
3
4
//npm
npm install recoil
//yarn
yarn add recoil

RecoilRoot

  • Recoil에서 상태를 관리하기 위해 사용되는 컨테이너 컴포넌트

recoil에서 제공하는 RecoilRoot를 앱의 최상위 컴포넌트를 감싸야 한다. 그래야만 recoil의 원자(Atom)를 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
//index.js or App.js
import React from "react";
import ReactDOM from "react-dom";
import { RecoilRoot } from "recoil";
import App from "./App";

ReactDOM.render(
  <RecoilRoot>
    <App />
  </RecoilRoot>,
  document.getElementById("root")
);

Atom

Recoil에서 atom은 상태를 나타내는 최소 단위이다.

  • key: 고유한 키를 지정하여 해당 상태를 식별
  • default: 초기 상태 값 지정
1
2
3
4
5
6
7
//atom.js
import { atom } from "recoil";

export const countAtom = atom({
  key: "count",
  default: 0,
});

Atoms Hook

atom은 useRecoilState, useRecoilValue, useSetRecoilState와 같은 Recoil 훅을 사용하여 해당 상태에 접근할 수 있습니다.

💡 useRecoilState

useRecoilState 훅은 두 개의 값 [state, setState]를 반환하며

  • state: 원자(Atom)의 현재 값을 읽을 수 있다
  • setState: 원자(Atom)의 상태를 변경할 수 있다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { useRecoilState } from "recoil";
import { countAtom } from "./atoms";

export default function App() {
  const [count, setCount] = useRecoilState(countAtom);

  const increment = () => setCount(count + 1);
  const decrement = () => setCount(count - 1);

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={increment}>더하기</button>
      <button onClick={decrement}>빼기</button>
    </div>
  );
}

💡 useRecoilValue

원하는 원자(Atom)의 상태를 읽기 위해 사용되며 해당 원자(Atom)의 최신 상태를 반환한다. 만약 컴포넌트가 이 원자(Atom)를 사용하고 있다면, 상태가 변경될 때마다 자동으로 리렌더링된다.

1
2
3
4
5
6
7
8
import { useRecoilValue } from "recoil";
import { countAtom } from "./atoms";

export default function App() {
  const count = useRecoilValue(countAtom);

  return <h1>Count: {count}</h1>;
}

💡 useSetRecoilState

원하는 원자(atom)의 상태를 변경할 수 있는 함수를 반환한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { useSetRecoilState } from "recoil";
import { countAtom } from "./atoms";

export default function App() {
  const setCount = useSetRecoilState(countAtom);

  const addOnClick = () => setCount((prevCount) => prevCount + 1);

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={addOnClick}>증가</button>
    </div>
  );
}

💡 Selector

Selectors는 하나 이상의 원자(Atom)로부터 값을 계산하는 데 사용되는 기본 개념이다.

  • get: 매개변수를 통해 원자(Atom)의 값을 접근할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//atom.js
import { atom, selector } from "recoil";

//현재 예산
export const budgetAtom = atom({
  key: "budget",
  default: 70000,
});

//구매 금액
export const buyAmountAtom = atom({
  key: "buyAmount",
  default: 30000,
});

//현재 남은 예산
export const remainingAmountAtom = selector({
  key: "remainingAmount",
  get: ({ get }) => {
    const budget = get(budgetAtom); // 70000
    const buyAmount = get(buyAmountAtom); // 30000
    return budget - buyAmount; // 40000
  },
});

//App.jsx
import { useRecoilValue } from "recoil";
import { remainingAmountAtom } from "./atoms";

export default function App() {
  const money = useRecoilValue(remainingAmountAtom); // 40000

  return <h1>money: {money}</h1>;
}

그리고 비동기 통신을 통한 데이터를 담고 있는 selector가 필요하다면 async/await 사용해서 해결 할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//atom.js
import { selector } from "recoil";

//유저ID
export const userIdAtom = atom({
  key: "userId",
  default: "taewok",
});

//유저 정보
export const userInfoAtom = selector({
  key: "userInfo",
  get: async ({ get }) => {
    const userId = get(userIdAtom);
    const res = await axios.get(`https://api.example.com/users/${userId}`);

    return res;
  },
});

💡 selectorFamily

파라미터화된 Selector를 사용하기 위해 사용하는 recoil 함수이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//atom.js
import { selectorFamily } from "recoil";

//유저 정보
export const userInfoAtom = selectorFamily({
  key: "userInfo",
  get:
    (userId) =>
    async ({ get }) => {
      const res = await axios.get(`https://api.example.com/users/${userId}`);

      return res;
    },
});

//App.jsx
import { useRecoilValue } from "recoil";
import { userInfoAtom } from "./atoms";

export default function App() {
  const userId = "taewok";
  const userInfo = useRecoilValue(userInfoAtom(userId));

  return <h1>{userInfo}</h1>;
}

마치며

혹시 잘못된 정보나 궁금하신 게 있다면 편하게 댓글 달아주세요.
지적이나 피드백은 언제나 환영입니다.

This post is licensed under CC BY 4.0 by the author.