FE/리뷰

[모던 리액트 딥다이브] 5.2장 리액트 훅으로 시작하는 상태 관리

따봉치치 2024. 8. 11. 18:49

useState와 useReducer
  • useState 
    • 여러 컴포넌트에 걸쳐 손쉽게 동일한 인터페이스의 상태를 생성하고 관리할 수 잇게 됨
  • useReducer
    • useState는 useReducer로 구현이 된 훅임
  • 두 개의 훅 모두 만들기에 따라 재사용할 수 있는 지역 상태를 만들어 주지만 이는 지역 상태라는 한계 때문에 여러 컴포넌트에 걸쳐 공유하기 위해서는 컴포넌트 트리를 재설계 하는 등의 수고로움이 필요함

 

 

Recoil
  • 리액트를 만든 페이스북에서 만든 리액트를 위한 상태 관리 라이브러리
  • 최소 상태 개념인 Atom을 처음 리액트 생테계에서 선보임
  • 실제 프로덕션에 사용하기에는 안정성, 성능, 사용성을 보장할 수 없음
  • Recoil의 상태값은 RecoilRoot로 생성된 Context의 스토어에 저장됨
  • 스토어의 상태값에 접근할 수 있는 함수들이 있으며, 이 함수들을 활용해 상태값에 접근하거나 상태값을 변경할 수 있음
  • 값의 변경이 발생하면 이를 참조하고 있는 하위 컴포넌트에 모두 알림
  • Recoilroot
    • Recoil을 사용하기 위해 RecoilRoot를 애플리케이션의 최상단에 선언해 둬야 함
    • Recoilroot에서 Recoil에서 생성되는 상태값을 저장하기 위한 스토어를 생성함
  • atom
    • 상태를 나타내는 Recoil의 최소 상태 단위
    • key 값을 필수로 가지며 다른 atom과 구별하는 식별자가 되는 필수 값
  • useRecoilValue
    • atom의 값을 읽어오는 훅
  • useRecoilState
    • useState와 유사하게 값을 가져오고, 이 값을 변경할 수 있는 훅
  • 특징
    • 다양한 비동기 작업을 지원하는 API를 제공하기 때문에 redux-saga, redux-thunk 등 추가적인 미들웨어를 사용하지 않아도 됨

 

Jotai
  • Recoil의 atom 모델에 영감을 받아 만들어진 상태 관리 라이브러리
  • 상향식 접근법을 취함 => 작은 단위의 상태를 위로 전파할 수 있는 구조
  • Context의 문제점인 리렌더링 문제와, 추가적으로 메모이제이션이나 최적화를 거치지 않아도 리렌더링이 발생되지 않도록 설계됨
  • atom
    • 최소 단위의 상태
    • atom 하나만으로도 상태를 만들 수도, 이에 파생된 상태를 만들수도 있음
    • 별도의 key를 넘겨주지 안하오 됨
    • config라는 객체를 반환함
  • useAtomValue
    • recoil과 다르게 컴포넌트 루트 레벨에서 Context가 존재하지 않아도 됨
    • atom의 값은 atom이 가지고 있는 것이 아니라 store에 존재 함
    • store에 atom 객체 그 자체를 키로 활용해 값을 저장함 => WeakMap 방식
  • useAtom
    • useState와 동일한 형태의 배열을 반환함
    • atom의 현재 값을 나타내는 useAtomValue 훅의 결과를 반환하며, 두번째로는 useSetAtom 훅을 반환함
  • 특징
    • Recoil의 atom 개념을 도입하면서도 API가 간결함
    • 사용자가 키를 관리할 필요가 없음
    • selector없이 atom만으로 atom 값에서 또 다른 파생된 상태를 만들 수 있음
import {atom, useAtom, useAtomValue} from 'jotai'

const couterState = atom(0);

function Counter() {
    const [,setCount] = useAtom(counterState);

    function handleBtnClick() {
        setCount((count) => count+1);
    }

    return (
        <>
            <button onClick={handleBtnClick}>+</button>
        </>
    )
}

 

 

 

 

Zustand
  • 리덕스에 영감을 받아 만들어짐
  • 하나의 스토어에서 중앙 집중형으로 활용해 이 스토어 내부에서 상태를 관리하고 있음
  • createStore를 사용하면 리액트와 상관없는 바닐라 스토어를 만들 수 있음
  • 특징
    • 특별히 많은 코드를 작성하지 않아도 빠르게 스토어를 만들고 사용할 수 있음
    • 간단하고 빠르게 상태를 정의할 수 있음
    • 라이브러리도 굉장히 작음
    • 타입스크립트를 기반으로 작성돼 있음
    • 리덕스와 마찬가지로 미들웨어를 지원함
import { create } from "zustand";

const useCounterStore = create((set) => ({
  count: 1,
  inc: () => set((state) => ({ count: state.count + 1 })),
  dec: () => set((state) => ({ count: state.count - 1 })),
}));

function Counter() {
  const [count, inc, dec] = useCounterStore();

  return (
    <>
      <span>{count}</span>
      <button onClick={inc}>+</button>
      <button onClick={dec}>-</button>
    </>
  );
}