next.js 환경에서 recoil 로 상태관리
recoil 은 상태관리 라이브러리이다.
react-redux 에 비해 코드가 간결해서 사용하기 쉽다.
설치
npm i recoil
atoms.js
atom 이라는 전역 객체를 만들어서 데이터를 관리한다.
import { atom } from 'recoil';
export const 데이터Atom = atom({
key: 'key 지정',
default: undefined, // 기본값 지정
})
_app.js
_app.js 에서 컴포넌트를 RecoilRoot
로 감싸 recoil 데이터를 전역으로 전달한다.
import { RecoilRoot } from 'recoil';
function App({ Component, pageProps }) {
return (
<RecoilRoot>
<Component {...pageProps} />
</RecoilRoot>
)
}
useRecoilState
데이터를 호출 및 출력할 컴포넌트에서 useState()
가 아닌 useRecoilState()
로 state 를 생성해 데이터를 Recoil 에 보관한다.
redux 의 dispatch 하는 느낌.
import { useEffect } from 'react';
import { useRecoilState } from 'recoil';
import { 데이터Atom } from '../atoms';
export default function Page() {
const [Items, setItems] = useRecoilState(데이터Atom);
const fetchData = async ()=>{
const data = await fetch(API_URL);
const result = await data.json();
setItems(result);
}
useEffect(()=>{
fetchData();
}, [])
return (
<main>
</main>
);
}
useRecoilValue
단순히 저장된 데이터를 불러오기만 한다면 useRecoilValue()
를 사용한다.
import { useRecoilValue } from 'recoil';
import { 데이터Atom } from '../atoms';
export default function Page() {
const Items = useRecoilValue(데이터Atom);
return (
<main>
</main>
);
}
useSetRecoilState
상태 데이터를 읽어오지 않고 업데이트만 하려고 할때 사용한다.
useResetRecoilState
상태를 초기화한다.
atom 선언 시 설정했던 default 값으로 되돌린다.
selector
selector는 atom 또는 selector 를 참조해서 새로운 값을 return 하는 순수함수이다.
참조하는 atom 이 업데이트 되면 따라서 업데이트 된다.
atom 에는 최소한의 값만 저장하고 이로부터 유도된 값을 selector 로 관리하는 것이 좋다.
API 호출 함수를 순수함수 형태로 분리해서 관리할 수 있다.
먼저 API 호출을 위한 api.js 파일을 생성한다.
import { selectorFamily } from 'recoil';
export const get데이터 = selectorFamily({
key: 'key',
get: () => async () => {
const data = await fetch(API_URL);
const result = await data.json();
return result;
},
})
커스텀 hook 을 생성해 API 데이터를 atom 객체에 적용한다.
setData.js 파일을 components 폴더에 생성한 후 SetData()
함수를 만들어 데이터를 atom 객체에 저장했다.
import { useEffect } from 'react';
import { 데이터Atom } from '../atoms';
import { get데이터 } from '../api';
import { useRecoilState, useRecoilValue } from 'recoil';
export default function setData() {
const setItems = useSetRecoilState(데이터Atom);
const result = useRecoilValue(get데이터());
useEffect(()=>{
setItems(result);
}, []);
return null;
}
호출할 컴포넌트에서 Suspense 를 이용해 SetData 컴포넌트가 데이터를 불러올때까지 기다렸다가 아래 코드를 실행하도록(컴포넌트를 마운트 시키도록) 동기화 처리한다.
<React.Suspense fallback={<p>loading...</p>}>
<SetData />
</React.Suspense>
<출력컴포넌트>