- Published on
React State Management Library <Recoil>
- Authors
- Name
- Easyoon
[Study] React State & Recoil (1)
리엑트의 상태관리에 자주 쓰이는 방식들
컴포넌트 합성(리엑트 내장)
context-API (리엑트 내장)**
- **context 사용 시, 중간 엘리먼트들에게 props를 넘길 필요 없음
- context에서는 컴포넌트가 상태의 특정 값에 의존할 경우, 해당 값 말고 **다른 값이 변경될 때도 컴포넌트가 리렌더링 -**Redux는 상태의 특정 값을 컴포넌트에서 의존하게 될 때 해당 값이 바뀔 때에만 리렌더링이 되도록 최적화
- Redux**
- **action
- reducer
- store 상태 변화
- 비동기 처리를 할 때, Redux는 Redux saga나 Redux Thunk 미들웨어를 추가로 설치해서 사용 왜?
- Redux Saga(비동기 처리 라이브러리)**
- **데이터를 요청하는 action
- saga가 action에 맞는 제너레이터 함수를 실행
- 제너레이터 함수에서 또 다른 reducer를 실행
- reducer에 따른 store 상태 변화
- Recoil
- context API 기반으로 구현
- 함수형 컴포넌트에서만 사용 가능
- 페이스북에서 만든 라이브러리
- 코드 분리가 쉬워 hook처럼 가져다 쓸 수 있다
Redux VS Recoil Github Sample
https://github.com/chandan-reddy-k/redux-vs-recoil-example
Atoms
Recoil에서 상태의 단위를 의미하며, 동일한 atom이 여러 컴포넌트에서 사용되는 경우 모든 컴포넌트는 상태를 공유한다.
업데이트, 구독이 가능한데 atom이 업데이트되면 각각의 구독된 컴포넌트는 새로운 값을 반영해서 리렌더링된다.
Atoms는 리액트의 로컬 state대신 사용할 수 있다. Atoms에는 중복이 되지 않는 고유 키가 필요하며, 각 atom은 디폴트 값도 가진다.
컴포넌트에서 atom을 읽고 쓸 때는 useRecoilState라는 훅을 사용하는데, 리액트의 useState와 비슷하지만 상태가 컴포넌트간에 공유될 수 있다는 점에서 차이가 있다.
Selector
Selectors는 상태를 기반으로 데이터를 계산하고 최소한의 상태 집합만 atoms에 저장하고, 파생 데이터는 selector에서 계산하면서 불필요한 상태를 만들어내지 않는다. 컴포넌트 관점에서 atoms와 selectors는 동일한 인터페이스이므로 대체 가능하다.
여기서 get속성은 계산될 함수를 의미하고 전달되는 get인자를 통해 atoms와 다른 selectors에 접근 가능하다. 여기서 접근하면 자동으로 종속 관계가 생성되어 참조했던 atoms나 selectors가 업데이트되면 이 함수도 재실행된다.
Selectors는 useRecoilValue()를 통해 조회 가능하다. useRecoilState와는 다르게 writable 하지 않고, 반환 값의 조회만 가능하다. 필요하다면 writable한 selector 작성도 가능하다.
- Heidi 공유 영상 : https://www.youtube.com/watch?v=7nwpEiSpPqY
get을 통해 QueryDataState을 구독 => QueryDataState가 변경될 때마다 api가 실행되는 방식 질문) 구독 말고 그냥 실행시키는 방법은 없을까? 없다. 기본적으로 selector는 atom의 파편의 일부이기 때문에.
- 프로젝트 내 커스텀 axios 분리 필요
실제 API 적용
import { atom, selector } from "recoil";
import axios from 'axios';
// page랑 등등 구독
export const loginAtom = atom({
key : 'loginAtom',
default: {
email: 'id',
password: 'pwd'
}
})
// 구독한 걸 바탕으로 selector 호출
export const loginSelector = selector({
key: 'loginSelector',
get: async ({ get }) => {
const data = get(loginAtom);
const {email, password} = data;
axios({
method: 'post',
url: '/api/users/login',
params: {
userId: email,
password: password
},
}).then(() => {
}).catch((err) => {
console.error(err);
})
}
});