Recoil
Recoil은 React를 위한 상태 관리 라이브러리다.
따라서 Recoil을 사용하기 위해서는 React가 설치되어 있어야 한다. React 애플리케이션을 시작하는 가장 쉽고 추천하는 방법은 Create React App을 사용하는 것이다.
시작.
npm install recoil
RecoilRoot
redux의 provider처럼 recoil 상태를 사용하는 컴포넌트는 RecoilRoot로 부모 트리를 감싸준다.
import React from 'react';
import {
RecoilRoot, //provider 느낌
atom, //원소(기본 상태)
selector, //원소를 이용하여 실행하는 기본함수(액션, 디스패치)
useRecoilState, //atom을 사용할 때
useRecoilValue, //selector을 사용할 때
} from 'recoil';
function App() {
return (
<RecoilRoot>
<CharacterCounter />
</RecoilRoot>
);
}
Atom
const textState = atom({
key: 'textState',
// RecoilRoot로 감싼 모든 곳에 전역적으로 사용되기에 중복되지 않는 고유 키값을 사용해야한다. (with respect to other atoms/selectors)
default: '',
// 초기값
});
컴포넌트가 atom을 읽고 쓰게 하기 위해서는 useRecoilState()를 아래와 같이 사용하면 된다.
*React의 useState와 비슷하지만, 상태가 컴포넌트 간에 공유될 수 있다는 차이가 있다.
function CharacterCounter() {
return (
<div>
<TextInput />
<CharacterCount />
</div>
);
}
function TextInput() {
const [text, setText] = useRecoilState(textState);
const onChange = (event) => {
setText(event.target.value);
};
return (
<div>
<input type="text" value={text} onChange={onChange} />
<br />
Echo: {text}
</div>
);
}
Selector
Selector는 atoms나 다른 selectors를 입력으로 받아들이는 순수 함수(pure function)다.
상위의 atoms 또는 selectors가 업데이트되면 하위의 selector 함수도 다시 실행된다.
컴포넌트들은 selectors를 atoms처럼 구독할 수 있으며 selectors가 변경되면 컴포넌트들도 다시 렌더링 된다.
Selectors는 상태를 기반으로 하는 파생 데이터를 계산하는 데 사용된다.
*최소한의 상태 집합만 atoms에 저장하고 다른 모든 파생되는 데이터는 selectors에 명시한 함수를 통해 효율적으로 계산함으로써 쓸모없는 상태의 보존을 방지한다.
const charCountState = selector({
key: 'charCountState',
// RecoilRoot로 감싼 모든 곳에 전역적으로 사용되기에 중복되지 않는 고유 키값을 사용해야한다. (with respect to other atoms/selectors)
get: ({get}) => {
const text = get(textState);
return text.length;
},
});
get 속성은 계산될 함수다. 전달되는 get 인자를 통해 atoms와 다른 selectors에 접근할 수 있다. 다른 atoms나 selectors에 접근하면 자동으로 종속 관계가 생성되므로, 참조했던 다른 atoms나 selectors가 업데이트되면 이 함수도 다시 실행된다.
Selector는 useRecoilValue를 사용해 읽을 수 있다. useRecoilValue는 하나의 atom이나 selector를 인자로 받아 대응하는 값을 반환한다.
function CharacterCount() {
const count = useRecoilValue(charCountState);
return <>Character Count: {count}</>;
}