Recoil 찍먹

jce1407·2021년 4월 22일
0

Recoil

목록 보기
1/2
post-thumbnail

Mobx는 어느정도 사용할줄 알게되어서 가장 악명높은 Redux 를 할려고 했었는데. . .
분명 좀 어렵겠지 했지만 공부하면 할수록 너무 어려워서 결국 Recoil 찍먹 결정! 😊

Recoil 뭘까?

**Recoil**은 페이스북에서 만든 React전용 상태 관리 라이브러리 이다!

Recoil 어쩌다 개발 되었을까?

상태관리를 위한 라이브러리는 대표적으로 Redux, Mobx등 여러가지가 이미 사용되고있다.
여전히 잘 사용되고있고 문제없는 좋은 라이브러리인데, 왜 Recoil이 나오게 된걸까?

ReduxMobx같은 라이브러리는 ** React전용 상태 관리 라이브러리가 아니기 때문에
React 내부 스케쥴러에 접근할 수 없고, 작은 기능하나 만드는데에도 ** 긴 코드
를 써야하는 번거로움이 있다🤔

Recoil의 장단점!

** 장점 **

  • ** React 자체 라이브러리**
    ↪ Redux, Mobx와 다르게 Recoil은 ** React의 전용 상태관리 lib**이기 때문에
    ↪ React 내부에서 접근이 가능하며 React 동시성 모드 Suspense 등이 쉽게 지원된다!

  • ** 적은 코드라인과 보일러 플레이트 **
    Redux를 공부했을 때 무언가 작은 것 하나 만들어 보려하면 수많은 보일러 플레이트가 필요했다.
    ↪ **Recoil**은 훨씬 적은 코드라인으로 가능하지롱 😁😁😁

  • ** 공부하기가 쉽다! **
    ↪ 지극히 개인적인 의견이긴 하지만 Redux, MobX를 공부할 때 보다 훨씬 쉬웠다!

** 단점 **

  • ** Hooks **
    ↪ Recoil의 API는 대부분 Hooks형태로 있어서 Hooks가 생소한 사람들에게는 ** 러닝커브**가 조금 있을 수 있다.

  • ** 라이브러리 개발중 **
    ↪ 아직 페이스북에서 열심히 개발중인 Lib라서 실서비스까지 보고 쓰기에는 다소 힘들 수 있다.

  • ** 디버깅 도구**
    ↪ 위에서 말했듯이 라이브러리가 아직 개발중이기 때문에 디버깅도구의 지원이 미미하다 😂

Atom

Atom은 하나의 상태라고 볼 수 있다. 이 값은 컴포넌트에서 구독할 수 있고,
Atom의 값이 바뀌게 되면 해당 Atom을 구독하고있던 ** 모든 컴포넌트들이 리렌더링** 된다.
Redux에서는 render단위로 state를 구성했는데, Atom은 이런 reducer 단위가 아닌 더 잘게 쪼개진 state 단위로 상태를 관리하게 된다.

Atom을 생성하기 위해선 어플리케이션에서 고유한 키 값과 기본 값을 설정해줘야한다.
➡ 기본 값은 정적인 값, 함수 심지어 비동기 함수까지도 지원 예정이라고 한다.)

** Atom 예시 **
keynameState, 기본 값Son Min Jae라고 주었다.

Selector

selector는 atom의 상태에 의존하는 동적인 데이터를 생성한다.
selector에서는 get함수(필수)를 통해 atom정보들을 1개 이상 가져올 수 있습니다.
이를 통해 atom을 조합해 새로운 데이터를 생성할 수 있습니다.

물론 atom의 정보가 바뀌면 해당 atom을 의존하는 selector도 자동으로 리렌더링 됩니다.
또한 Selector에서 한 개 이상의 atom정보를 업데이트 하도록 set함수(선택)을 받을 수 있습니다.

get 함수만 제공되면 Selector는 읽기만 가능한 RecoilValueReadOnly 객체를 반환하고
set 함수도 제공되면 Selector는 쓰기 가능한 RecoilState 객체를 반환합니다.

Selector 예시
↪ get만 했어용

Recoil 상태와 상태 변경 함수

컴포넌트에서 atom과 selector를 위해 쓰는 함수들은 크게 4가지로 분류됩니다.

** 1. useRecoilState ➡ atom이나 selector의 상태와 setter함수를 받는다.
2. useRecoilValue ➡ atom이나 selector의 상태만 받는다.
3. useSetRecoilState ➡ atom이나 selector의 setter함수만 받는다.
4. useResetRecoilState ➡ atom이나 selector의 상태를 기본 값으로 지정하는 함수를 받는다. **

import { nameState } from './somewhere';
// useRecoilState => 상태와 setter함수 둘다 가지고 오기
const NameInput = ( => {
	const [name, setName] = useRecoilState(nameState);
	const onChange = (event) => {
		setName(event.target.value);
	};
	return (
		<input type="text" value={name} onChange={onChange} />
		<div> Name: {name} </div>
	);
}

// useRecoilValue => 상태만 가지고오기
const OtherComponentWithName = () => {
	const name = useRecoilValue(nameState);
	return <div> {name} </div>; 
}

// useSetRecoilState => setter함수만 가져오기 
const OtherComponentThatSetName = () => {
	const setName = useSetRecoilState(nameState);
	return <button onClick={() => setName('Min Jae')}> Set Name </button>;
}

// useResetRecoilState => atom이나 selector의 상태를 기본 값으로 바꿔주는 함수
const OtherComponentThatResetName = () => {
	const onClickBtn = useResetRecoilState=(nameState);
  	return <button onClick={() => onClickBtn()}> Reset </button>;
}

Selector의 특이점

캐싱지원
selector를 통해 비동기 통신을 할 때 가장 큰 장점중 하나입니다.
자체적으로 캐싱을 지원하기 때문에 같은 액션에 있어서 캐싱된 결과를 바로 보여주기 때문에
퍼포먼스 면에서도 훨씬 유리 합니다.

비동기 제어
Recoil에서는 Suspense를 사용하지 않고 비동기를 제어할 수 있습니다.
바로 useRecoilValueLoadableuseRecoilStateLoadable을 쓰는거죠 😁

  • ** useRecoilValueLoadable ** ➡ 현재 비동기 작업의 상태 값을 받아온다.
  • ** useRecoilStateLoadable ** ➡ 현재 비동기 작업의 상태 값 과 setter함수를 받아온다.

Loadable을 통한 상태

  • state ➡ 비동기 상태를 나타내며 hasValue(값이 존재) , loading(로딩중), hasError(에러발생) 이렇게 3가지 상태가 존재합니다.

  • contents ➡ 비동기 통신의 ** 결과 값 ** 입니다.
    위에서 말한 state별로 값이 달라지는데요 hasValue일때는 valueloading일때는 PromisehasError이면 Error 객체로 됩니다.

Redux에서는 각 state에 대한 비동기 상태를 별도로 가져야 하지만 Recoilselector는 비동기 상태에 대한 정보는 담고 있지 않아도 **useRecoilLoadable**에서 지원해줌으로 훨씬 깔끔합니다.

** Loadable ** 예시

import { useRecoilState, useRecoilValueLoadable } from 'recoil';
import {delayCountState, delay1SecSelector} from './recoil/delayCount';

function DelayCount() {
  const delay1Sec = useRecoilValueLoadable(delay1SecSelector); 
  // delay1Sec라는 변수에 useRecoilValueLoadable로 delay1SecSelector의 상태 값만 받아오고
  const [delayCount, setDelayCount ] = useRecoilState(delayCountState);
  // useRecoilState로 delayCountState의 상태와 setter함수를 받아온다.

  if(delay1Sec.state === 'loading') { 
    // loadable으로 받아온 변수의 상태가 loading이면 로딩중이라고 띄워주기
    return (<div>로딩중 입니둥 ~ </div>);
  }

  return (
    <>
      <h3>캐싱된 selector 값 </h3>
      <p>{delay1Sec.contents}</p>
      <button onClick = {() => setDelayCount(delayCount + 1)}>증가</button>
      <button onClick = {() => setDelayCount(delayCount - 1)}>감소</button>
    </>
  );
};

export default DelayCount;

개념정리를 끝내면서. . .

Redux가 너무 어려워서 Recoil로 방향을 틀어서 공부를 하고있습니다.
Recoil은 러닝커브도 낮고 코드도 간결하면서 번거로움이 적어 제 취향에 너무 잘 맞는 라이브러리인것 같아요! 😆
아직 AtomFamilySelectorFamily Selector-set 등 여러가지 개념들이 남았으니까 추후에 더 올리도록 할게요!
감사합니다. 😎

참고한 문서 및 블로그들
VELOG1 / VELOG2 / Blog1 / Blog2 / Blog3 / Blog4 / Blog5 / Blog6Blog7 / Recoil

profile
최고의 복지는 좋은 동료, 좋은 동료가 되기 :)

관심 있을 만한 포스트

0개의 댓글