Sua Blog
상태관리를 redux로만 사용했었는데 필요한 상태하나가 추가될 때 필요로 하는 코드, 파일의 양이 많아 불편함이 있었다. 내가 원하는 상태를 빠르게 저장하고 쓰고 싶어 recoil을 사용해보았다.
recoil 특징
- 상태 변화는 공유상태(atom)으로 부터 순수함수(selectors)를 거쳐 컴포넌트로 흐른다.
- 전역 상태도 React의 내부 상태처럼 간단한 get/set 인터페이스로 사용할 수 있도록 보일러 플레이트 없이 제공한다.
- 동시성 모드(Concurrent Mode)등 React의 기능들과 호환이 된다.
Atom
Atom은 상태의 단위이고 업데이트와 구독이 가능하다. atom의 값을 읽는 컴포넌트들은 암묵적으로 atom을 구독한다. 그래서 atom에 어떤 변화가 있으면 그 atom을 구독하는 모든 컴포넌트들이 다시 렌더링 된다.
Atom은 atom()함수를 사용해 생성한다.
const fontSizeState = atom({
key: 'fontSizeState',
default: 14,
});
키 값은 전역적으로 고유해야하고 React 컴포넌트의 상태처럼 기본값을 가진다.
컴포넌트에서 atom을 읽고 쓰려면 useRecoilState()을 사용한다.
Selector
Selectors는 atoms 상태값을 동기 또는 비동기 방식을 통해 변환한다. Selector 값은 순수 함수에 전달된 상태의 결과물로 생각할 수 있다.
useRecoilValue() 훅을 사용해서 값을 읽을 수 있다.
블로그에 적용
기존 블로그 메인 색상을 어둡게 정했었는데 보는데 불편함이 있는 것 같아 recoil로 day, night 모드 상태를 만들어 작업해 보았다.
recoil을 사용할 때는 컴포넌트 최상위 부모 트리에 <RecoilRoot>로 감싸주어야한다.
나는 _app.tsx파일에 기존 <Layout> 컴포넌트를 감싸주었다.
state폴더를 만들고 atom함수를 사용해 modeState를 생성하고 default값은 'night'로 설정하였다.
Layout 컴포넌트에서 modeState의 상태 값을 받아와 클래스에 적용하는 방식으로 작업하였다.
Duplicate atom key Warning
모드 버튼을 누를 때 마다 상태값이 잘 변화되고 재렌더링되는데는 문제가 없지만 Next.js 콘솔에서 Warning이 출력되었다.
Expectation Violation: Duplicate atom key "modeState". This is a FATAL ERROR in
production. But it is safe to ignore this warning if it occurred because of
hot module replacement.
에러가 발생하는 이유는 SSR이어서 여러번 atom을 생성하여 경고 메세지가 출력되는 것이다.
해당 에러는 공식 이슈로 아직 해결되지 않아 무시하여도 된다고 하였다.
하지만 개발중 warning을 항상 보고싶지는 않아 해결방법을 찾아봤다. 단순히 recoil 패키지에 들어가 console.warn()을 주석하는 방법이 있고 중복 key가 되지않도록 uuid()사용하여 난수를 생성하고 key값을 변경해주는 방법이 있다.
패키지 업데이트를 하면 또 수정을 해줘야하는 전자보다 후자가 계속 쓸 수 있는 방법인것 같아 두번째 방식으로 해결하였다.
import { atom } from 'recoil';
import { v1 } from 'uuid';
export const modeState = atom({
key: `modeState/${v1()}`,
default: 'night',
});
참고
https://recoiljs.org/ko/docs/introduction/motivation
https://parkgang.github.io/blog/2021/05/06/using-recoil-in-nextjs/