컴포넌트의 규모가 커지며 props로 state를 전달하는 방식으로 상태를 관리하는 것은 적합하지 않다는 생각을 하게되었다.(전달하는 과정의 코드가 더럽고 복잡) 따라서 간편하게 전역 상태를 관리할 수 있는 recoil을 도입하기로 하였다.
또한, React는 단방향으로 바인딩하는 라이브러리여서, 부모 -> 자식 방향으로만 state를 props로 전달할 수 있고, 자식의 props를 부모에게 전달하는 방법은 존재하지 않는다.
하지만! 상태 관리 툴을 이용하면 자식 component에서 부모 component의 state를 바꿀 수 있다.
Recoil: Facebook에서 발표한 React 상태관리 라이브러리
1️⃣ recoil 설치
npm install recoil
2️⃣ recoil 사용하기
🔎 RecoilRoot
recoil을 사용할 컴포넌트의 부모 트리에 위치시켜야한다. (루트 컴포넌트에 많이 위치 시킴)
- index.js
import { AppRegistry } from 'react-native';
import App from './src/App';
import { name as appName } from './app.json';
import { RecoilRoot } from 'recoil';
const Root = () => (
<RecoilRoot>
<App />
</RecoilRoot>
);
AppRegistry.registerComponent(appName, () => Root);
🔎 Atom
Atom은 상태(state)의 일부를 나타내며, 업데이트와 구독이 가능하다. atom에 변화가 있으면 atom을 구독하는 모든 컴포넌트가 재 렌더링 된다.
- isTabletAtom.js
import { atom } from 'recoil';
export const isTabletAtom = atom({
key: 'isTablet',
default: null,
});
- key: atom이 구분하는 유니크한 id이다.
- default: 초기값
🔎 Atom을 읽고 쓰는 방법
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
// 1. 읽기&쓰기
const [isTablet, setIsTablet] = useRecoilState(null);
// 2. 읽기만
const isTablet = useRecoilValue(isTabletAtom);
// 3. 쓰기만
const setIsTablet = useSetRecoilState(isTabletAtom);
3️⃣ 활용 사례
디바이스(태블릿, 휴대폰) 별로 각각 다른 컴포넌트를 사용하기 위해 recoil를 활용하였다.
useEffect를 활용해 isTablet 값이 변경될 경우에 atom을 업데이트 시킨다.
import React, { useEffect } from 'react';
import { useSetRecoilState } from 'recoil';
import { isTabletAtom } from './modules/recoil/isTabletAtom';
import { useWindowDimensions } from 'react-native';
const Stack = createNativeStackNavigator();
const App = () => {
const setIsTablet = useSetRecoilState(isTabletAtom);
const dimensions = useWindowDimensions();
const isTablet = dimensions.width >= dimensions.height;
// isTablet 값 변경 시 실행
useEffect(() => {
setIsTablet(isTablet);
}, [isTablet]);
...
}