React 상태 관리 라이브러리 Recoil-js 사용해보기

시작하기

리액트 유럽에서 리액트의 새로운 상태관리 라이브러리 recoil을 발표했습니다.
기존에 사용하던 redux 라이브러리와 어떤차이가 있는지 사용해보도록 하겠습니다.
Recoil js홈페이지에서 자세한 내용을 확인 할 수 있습니다.
Recoil 소개 유투브

설치하기

1
npx create-react-app my-app

프로젝트를 생성합니다.

1
npm install recoil

recoil을 설치합니다.

설정

Redux에서 최상단에 provider를 사용해주는 것과 같이 최상단에 RecoilRoot를 설정해주어야합니다.

index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import { RecoilRoot } from "recoil";

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

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
  • RecoilRoot : 프로젝트의 최상단에 설정해주어야 내부에서 recoil을 사용할 수 있습니다.
  • atom: key와 value를 설정해줍니다. 기본 state입니다.
  • selector: reducer와 흡사합니다. selector에서 atom의 값을 가져오고, switch문으로 매개변수의 해당부분을 찾아, 값을 변형시켜 반환할 수 있습니다.
  • useRecoilState: useState와 흡사하게 [value, setValue]형식으로 setValue로 값을 변경 할 수 있습니다.
  • useRecoilValue: 오로지 recoil의 값만 가져오고 싶으면 사용합니다.

사용하기

Counter예시를 만들어 보도록 하겠습니다.

src/Counter.js
1
2
3
4
5
6
7
8
9
10
11
import React from "react";

export default () => {
return (
<div>
<p>Counter Component State : 0</p>
<button type="button">+</button>
<button type="button">-</button>
</div>
);
};
src/App.js
1
2
3
4
5
6
7
8
9
10
11
12
13
import React from "react";
import Counter from "./Counter";

function App() {
return (
<>
<p>App Count State: 0</p>
<Counter />
</>
);
}

export default App;

컴포넌트를 추가합니다.

src/atoms.js
1
2
3
4
5
6
import { atom } from "recoil";

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

count의 state값을 설정합니다.

사용하기

src/Counter.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import React from "react";
import { useRecoilState } from "recoil";
import { CountState } from "./atoms";

export default () => {
const [count, setCount] = useRecoilState(CountState);
return (
<div>
<p>Counter Component State : {count}</p>
<button
type="button"
onClick={() => setCount((prevState) => prevState + 1)}
>
+
</button>
<button
type="button"
onClick={() => setCount((prevState) => prevState - 1)}
>
-
</button>
</div>
);
};
src/App.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from "react";
import Counter from "./Counter";
import { useRecoilValue } from "recoil";
import { CountState } from "./atoms";

function App() {
const count = useRecoilValue(CountState);
return (
<>
<p>App Count State: {count}</p>
<Counter />
</>
);
}

export default App;

실행을 해보면 다음과 같이 작동이 잘 되는것을 확인할 수 있습니다.
Counter 실행

Selector 사용하기

selector를 통해서 카운터가 증가인 상태인지 감소한 상태인지를 나타내는 라벨을 설정해보겠습니다.

src/atoms.js
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
import { atom, selector } from "recoil";

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

export const CountTypeState = atom({
key: "CountTypeState",
default: "normal",
});

export const CountLabelState = selector({
key: "CountLabelState",
get: ({ get }) => {
const count = get(CountState);
const countType = get(CountTypeState);
switch (countType) {
case "increment":
return `증가 => ${count}`;
case "decrement":
return `감소 => ${count}`;
default:
return `${count}`;
}
},
});

현재 카운터의 상태를 나타낼 CountTypeState 값,
CountTypeState값 변경에 따라 CountLabelState 다른값을 반환합니다.

src/Counter.js
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
import React from "react";
import { useRecoilState, useRecoilValue } from "recoil";
import { CountState, CountTypeState, CountLabelState } from "./atoms";

export default () => {
const [, setCount] = useRecoilState(CountState);
const [, setCountType] = useRecoilState(CountTypeState);
const countLabel = useRecoilValue(CountLabelState);
return (
<div>
<p>Counter Component State : {countLabel}</p>
<button
type="button"
onClick={() => {
setCountType("increment");
setCount((prevState) => prevState + 1);
}}
>
+
</button>
<button
type="button"
onClick={() => {
setCountType("decrement");
setCount((prevState) => prevState - 1);
}}
>
-
</button>
</div>
);
};

setCount로 카운터의 값을 변경하고, setCountType으로 지금 값이 increment인지 decrement인지 값을 저장합니다.
이후 selector를 통해 countLabel로 값이 나타납니다.

src/App.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from 'react';
import Counter from './Counter';
import { useRecoilValue } from 'recoil';
import { CountLabelState } from './atoms';

function App() {
const countLabel = useRecoilValue(CountLabelState);
return (
<>
<p>App Count State: {countLabel}</p>
<Counter />
</>
);
}

export default App;

Counter 실행

Recoil을 사용해보았는데 정말 만족스럽습니다.
redux의 경우 action reducers를 설정하고 combineReducers로 합쳐주고 사용할때는 dispatch를 통해서 사용을 하는 방식의 많이 복잡한 과정이 필요한데, recoil의 경우에는 hooks에 최적화되고 더욱 단순해진 것 같습니다.

Share