너무나도 많은 상태 관리 라이브러리 중 어떤 걸 배워볼까 고민하던 중에 가장 진입장벽이 낮은 게 Recoil이라고 들어 배워보려고 한다.
Redux 안해
npm install recoil
Recoil은 npm 패키지에 존재하므로 바로 설치할 수 있다.
function App() {
return (
<RecoilRoot>
<CharacterCounter />
</RecoilRoot>
);
}
Recoil을 사용하기 위해선 다음과 같이 최상위 컴포넌트를 RecoilRoot로 묶어줘야 한다.
Recoil의 가장 핵심적인 개념, Atom은 상태(state)의 일부를 나타낸다.
잠깐 useState를 복습해보면, 우리가 useState를 썼던 이유는 우리가 추적할 state가 바뀌었을 경우 해당 DOM을 랜더링 해주기 위해서였다. Atom 역시 state와 같은 개념이나, 다음과 같은 특징이 있다.
atom.ts
import { atom } from "recoil";
export const textAtom = atom({
key: "textAtom",
default: "",
});
CharacterInput.js
import React from "react";
import { useRecoilState } from "recoil";
import { textAtom } from "./atom.ts";
function CharacterInput() {
const [text, setText] = useRecoilState(textAtom); // useRecoilState: 값을 받아오고, 쓸 수 있는 훅, useState와 쓰임새는 동일!
const onChange = (e) => {
setText(e.target.value);
};
return (
<div>
<input type="text" value={text} onChange={onChange}></input>
</div>
);
}
export default CharacterInput;
TextInput.js 에서도 atom.ts에 선언한 Atom을 구독하는 식으로, ChracterInput.js의 input value값을 그대로 쓸 수 있다.
화면
TextInput.js
import React from "react";
import { textAtom } from "./atom.ts";
import { useRecoilValue } from "recoil";
function TextInput() {
const text = useRecoilValue(textAtom);
return (
<div>
<div className="again">{text}</div>
<div className="count">{text.length}</div>
</div>
);
}
export default TextInput;
useRecoilState는 atom의 값을 받아오고 수정할 수 있는 훅이다. useState와 쓰임새가 동일하다.
그전까지는 다른 컴포넌트에서 선언하였던 state를 사용하기 위해서 state 끌어올리기, props 무한지옥 등을 통해야 했지만 이제는 하나의 파일에 Atom들을 쭉 선언한 뒤 사용하고 싶은 컴포넌트에서 import 하여 useRecoilValue()훅을 통하여 가져오면 된다! (정말 편한 것 같다 이걸 왜 지금알았지..)

Selector는 파생된 상태(derived state)의 일부를 나타낸다. 파생된 상태는 상태의 변화다. 파생된 상태를 어떤 방법으로든 주어진 상태를 수정하는 순수 함수에 전달된 상태의 결과물로 생각할 수 있다.
-Recoil 공식문서
이것만 봐서는 무슨 말인지 이해하기 힘들었다.
다른 포스팅 글들을 참조해서 얻은 정보는..
Selector는 기존의 선언했던 atom을 통하여 새로운 값을 Return하거나, atom의 값 자체를 수정할 수 있는 기능을 가지고 있다. 또한 selector는 atom을 참조하기에, atom의 값이 최신화되면 selector 또한 최신화된다고 한다.
CharacterInput.js에서의 input value 뒤에 엄준식을 붙이는 엄준식체를 만드는 예제로 일단 바로 적용해보자.
atom.ts
import { atom, selector } from "recoil";
export const textAtom = atom({
key: "textAtom",
default: "",
});
// 추가된 코드
export const 엄준식체 = selector({
key: "엄준식체",
get: ({ get }) => get(textAtom) + "엄준식",
});
엄준식체는 위의 textAtom값을 참조하여 string 끝에 "엄준식"을 붙인 값을 리턴한다.
Selector에 문법에 주목해보면 atom 선언할 때와 마찬가지로 key가 존재하며, get에는 리턴할 값을 textAtom을 참조하여 위에처럼 사용한다.
TextInput.js
import React from "react";
import { textAtom } from "./atom.ts";
import { useRecoilValue } from "recoil";
import { 엄준식체 } from "./atom.ts";
function TextInput() {
const text = useRecoilValue(textAtom);
const umText = useRecoilValue(엄준식체);
return (
<div>
<div className="again">{text}</div>
<div className="umm">{umText}</div>
<div className="count">{text.length}</div>
</div>
);
}
export default TextInput;
useRecoilValue를 통하여 Selector로 선언한 엄준식체를 받아왔다.
보다시피 Selecctor를 사용하는 법은 atom과 동일하다!

엄준식체가 잘 나타나고 있는 걸 볼 수 있다!
위에서 구현한 엄준식체의 경우 Atom 의 값을 참조하여 get 을 통해 새로운 값을 리턴하였다. 다음엔 Atom 그 자체의 값을 수정해보자.