Recoil은 무엇인가?
Redux, Context API, useState처럼 상태관리
- 1. atom에 기본적인 틀만 있고, selector에서 초기값에 맞춰서 반환하는 경우
- 2. atom에 데이터가 다 있고, 각각의 selector에서 다른 데이터를 가져오는 경우
순서
1. atom 정의 -> 2. selector 정의 -> 3. 상태 업데이트 및 읽기(컴포넌트에서 아톰 연동)
-> 4. 아톰에 들어 온 값이 selector 에게 전달 -> 5. selector 는 들어 값에 추가 계산 또는 읽어 옴
Recoil
- 페이스북에서 개발한 상태 관리 라이브러리
- 컴포넌트 기반으로 상태를 관리할 수 있는 기능을 제공
Recoil에서 상태는 atom과 selector로 관리
RecoilRoot 설정
예시
// pages/_app.js
import { RecoilRoot } from 'recoil';
function MyApp({ Component, pageProps }) {
return (
<RecoilRoot>
<Component {...pageProps} />
</RecoilRoot>
);
}
export default MyApp;
- atom(기본 상태) : 상태의 단위 / 단순한 값을 저장
예시
import { atom } from 'recoil';
export const countState = atom({
key: 'countState', // 각 atom의 고유 key
default: 0, default: 0, // 기본값
});
- selector(파생 상태) : 아톰의 상태를 기반으로 새로운 값을 계산 / 캐싱을 통해 성능을 최적화하고 / 비동기 데이터를 처리
예시
import { selector } from 'recoil';
export const doubleCounterState = selector({
key: 'doubleCounterState',
get: ({ get }) => {
const count = get(counterState);
return count * 2;
},
});
- 원본유지 아톰에 영향을 주지 않고 파생된 셀렉터에서 새롭게 계산하여 다른 값을 반환
- 파생 상태는 원본 상태가 변경될 때마다 자동으로 업데이트
- 캐싱 셀렉터는 동일한 입력에 대해 캐싱을 수행하여 성능을 최적화
컴포넌트 활용
import { useRecoilValue, useRecoilState } from 'recoil';
import { countState, doubleCountState } from './path/to/your/states';
function Counter() {
const [count, setCount] = useRecoilState(countState);
const doubleCount = useRecoilValue(doubleCountState);
return (
<div>
<h1>Count: {count}</h1>
<h2>Double Count: {doubleCount}</h2>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setCount(count - 1)}>Decrement</button>
</div>
);
}
export default Counter;
문자, 데이터일 경우
1. RecoilRoot 설정
// pages/_app.js
import { RecoilRoot } from 'recoil';
function MyApp({ Component, pageProps }) {
return (
<RecoilRoot>
<Component {...pageProps} />
</RecoilRoot>
);
}
export default MyApp;
2. atom
// states/userState.js
import { atom } from 'recoil';
export const userState = atom({
key: 'userState',
default: {
name: '',
age: 0,
email: ''
},
});
3. selector
// states/userSelector.js
import { selector } from 'recoil';
import { userState } from './userState';
export const userNameState = selector({
key: 'userNameState',
get: ({ get }) => {
const user = get(userState);
return user.name;
},
});
4. 컴포넌트 활용
// components/UserProfile.js
import { useRecoilState, useRecoilValue } from 'recoil';
import { userState, userNameState } from '../states/userState';
function UserProfile() {
const [user, setUser] = useRecoilState(userState);
const userName = useRecoilValue(userNameState);
const updateName = (e) => {
setUser({ ...user, name: e.target.value });
};
return (
<div>
<h1>User Profile</h1>
<p>Name: {userName}</p>
<input type="text" value={user.name} onChange={updateName} placeholder="Enter your name" />
</div>
);
}
export default UserProfile;
----------------------------------------------------------------------------------------------------------------------------------------------------------
4. 비동기 데이터 패싱
// states/todoListState.js
import { atom, selector } from 'recoil';
import axios from 'axios';
export const todoListState = atom({
key: 'todoListState',
default: [],
});
export const todoListQuery = selector({
key: 'todoListQuery',
get: async () => {
const response = await axios.get('/api/todos');
return response.data;
},
});
5. 다중 selector
// states/shoppingCartState.js
import { atom, selector } from 'recoil';
export const cartItemsState = atom({
key: 'cartItemsState',
default: [],
});
export const cartTotalState = selector({
key: 'cartTotalState',
get: ({ get }) => {
const items = get(cartItemsState);
return items.reduce((total, item) => total + item.price * item.quantity, 0);
},
});
1. useRecoilState
useState와 유사하게 동작하며, 상태 값을 읽고 업데이트할 수 있는 튜플을 반환
2. useRecoilValue
useRecoilValue는 아톰이나 셀렉터의 값을 읽기만 할 때 사용
3. useSetRecoilState
useSetRecoilState는 상태 값을 설정하는 데 사용됩니다. 상태 값을 읽지 않고도 업데이트