React를 위한 전역 상태관리 라이브러리이다.
컴포넌트가 공유할 수 있는 상태의 단위로, state와 props와 같이 값을 가져오거나 변경하는 것이 가능하다.
atom 은 atom()
함수를 이용하여 생성할 수 있다. atom은 생성 시 고유 key
값을 지정해주어야 한다. 이 key
값을 기반으로 모든 컴포넌트에서 상태값을 불러오는 것이 가능하다.
const fontSizeState = atom({
key: 'fontSizeState',
default: 14,
});
실제 컴포넌트에서 atom 을 불러올 때는 useRecoilState()
를 통해 불러올 수 있다.
function FontButton() {
const [fontSize, setFontSize] = useRecoilState(fontSizeState);
// get,set 을 나누어 불러오는 것도 가능하다.
// const fontSize = useRecoilValue(fontSizeState);
// const setFontSize = useSetRecoilState(fontSizeState);
return (
<button onClick={() => setFontSize((size) => size + 1)} style={{fontSize}}>
Click to Enlarge
</button>
);
}
selector 는 atom 에서 파생된 데이터를 사용한다. 순수함수의 틀에서 atom 의 직접적인 상태 변질이 이루어지지 않도록 새로운 데이터를 반환하다. 즉 atom 을 구독한 상태에서 atom 이 변화하는 경우 그에 변경 값에 맞는 동적인 데이터를 형성한다. 이 때 상황에 따라 필요한 atom 을 결합하여 상태값을 제공하기도 한다.
마치 vue 의 watch와 computed를 사용하는 것과 비슷하다고 생각한다.
const userDetailsSelector = selector({
key: 'userDetails',
get: () => ({
userName: userNameAtom.get(),
emailAddress: emailAddressAtom.get(),
}),
});
selector 는 서버의 요청을 통해 반환되는 데이터를 저장하는 것도 가능하다. async 를 활용하여 결과가 반환된 후에 이를 컴포넌트에 적용하도록 새로운 결과를 반환하는 것이 가능하다.
const userDetailsSelector = selector({
key: 'userDetails',
get: async () => {
const response = await fetch('https://example.com/user/1');
const user = await response.json();
return user;
},
});
또한 React Suspense와 함께 결합하여 사용할 수 있어서, 응답 보류 상태의 처리도 가능하다.
function CurrentUserInfo() {
const user = useRecoilValue(userDetailsSelector);
return <div>{user.name}</div>;
}
function MyApp() {
return (
<RecoilRoot>
<React.Suspense fallback={<div>Loading...</div>}>
<CurrentUserInfo />
</React.Suspense>
</RecoilRoot>
);
}