이번엔 상태관리 라이브러리인 Recoil에 대해서 알아볼 것이다! Redux / ContextAPI / Mobx 등 여러 라이브러리를 써보고 느껴왔지만, 리코일에 대해서는 처음이라 한번 차근차근 알아보자
전역상태 관리 라이브러리 중 하나, 기존 리액트 개발자라면 쉽게 사용이 가능
prop drilling이 난무한 프로젝트 속에서 전역 상태 라이브러리 (Redux, Mobx...)등을 많이 사용하곤 하지만 Recoil은 Redux에 비해 간단하고, 비교적 보일러 플레이트 코드가 적음
(보일러 플레이트 코드 - 반복적으로 사용되는 코드조각이나 패턴) 따라서, 러닝 커브가 적은 것이 가장 핵심
하나의 상태로서, 아톰이 업덷이트 되면 해당 아톰을 구독(사용)하던 컴포넌트들의 리랜더링이 일어남
아톰을 사용하기 위해선 RecoilRoot 컴포넌트를 사용하려는 컴포넌트 상위에 부모 컴포넌트로 덮어준 후, 아톰에 Key와 Default 값을 설정해주면 됨
Key는 다른 아톰과 겹치지 않는 고유한 값으로 지정해주면 되고 default값은 초기값을 지정해주면 됨
// index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {RecoilRoot} from "recoil";
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
// 덮어주기
<RecoilRoot>
<App />
</RecoilRoot>
</React.StrictMode>
);
reportWebVitals();
// src > recoil > atoms > input.ts
import {atom} from "recoil";
export const inputState = atom({
key: 'inputState',
default: ''
})
// App.tsx
import React from 'react';
import {useRecoilState} from "recoil";
import {inputState} from "./input";
function App() {
const [input, setInput] = useRecoilState(inputState);
return (
<div>
<input value={input} onChange={(e) => {
setInput(e.target.value)
}} />
</div>
);
}
export default App;
그 후, 우리가 잘 아는 useState처럼 iseRecoilState를 사용하여 값을 사용하고 설정하면 됨
신기한 점은 값만 가져오고 싶거나, 세터함수만을 가져오고 싶을 때에 따로 hook를 제공하고 있다.
// const [input, setInput] = useRecoilState(inputState);
const input = useRecoilValue(inputState);
const setInput = useSetRecoilState(inputState);
...
파생된 상태 (derived state), 어떤 방법으로든 주어진 상태를 수정하는 순수함수에 전달된 상태의 결과물
Selector는 Recoil 내에서 상태값을 변환하거나 계산하기 위해 사용하고 Recoil 상태의 파생된 값을 만들기 위한 함수이다
입력값과 출력값이 같아야하는 순수함수
selector({
key: 'squaredSelector',
get: ({ get }) => {
const inputNumber = get(inputNumberState);
return inputNumber * inputNumber;
},
get: ({ get }) => {
const inputNumber = get(inputNumberState);
return inputNumber * inputNumber;
},
set: ({ set }, newValue) => {
const newInputNumber = Math.sqrt(newValue);
set(inputNumberState, newInputNumber);
},
})
key: atom의 키값과 동일하게 유일한 값이여야 한다.
get: derived state(파생 상태) 를 return 하는 메소드
set: writeable 한 state(atom) 값을 변경할 수 있는 메소드
간단한 API
: Recoil은 간단하고 직관적인 API를 제공하여 상태 관리를 쉽게 할 수 있음
성능 최적화
: 컴포넌트가 필요한 상태만 구독하고, 해당 상태가 변경될 때만 리렌더링되므로 성능이 최적화
동시성 지원
: React의 새로운 Concurrent 모드와 잘 통합되어 동시성을 지원
서로 다른 상태 간의 종속성 관리
: Selectors를 사용하여 상태 간의 종속성을 쉽게 관리할 수 있음
상대적으로 새로운 라이브러리
: React 생태계에서 비교적 새로운 라이브러리이므로, 커뮤니티와 문서화가 다른 상태 관리 라이브러리보다 부족
학습 곡선
: Atoms와 Selectors의 개념을 이해하고 사용하는 데 다소 학습 곡선이 있을 수 있음 (Redux 보단 덜 할 것 같은데..)
Recoil은 특히 복잡한 상태 관리를 단순화하고 성능을 최적화해야 하는 React 애플리케이션에 적합하다고 함
그러나 프로젝트의 요구사항에 따라 다른 상태 관리 솔루션과 비교하여 선택하는 것이 좋음