Zustand 튜토리얼 및 모달 구현하기

모아나·2024년 8월 2일
0

Zustand를 왜 쓰는가

리덕스는 상태관리로 많이 쓰이지만 보일러플레이트가 길다는 단점이 있다. 이에 recoil을 사용하였는데 확실히 보일러플레이트도 짧은 편이고, 코드가 직관적이라 이해가 쉬웠다.

그렇게 다음 프로젝트에서 Zustand와 recoil 사이 고민을 하게되는데 이런저런점을 따져보다 Zustand를 선택하게 되었다.


Zustand가 recoil보다 20배는 사이즈가 작다.
recoil은 최근 업데이트가 1년전인데 비해 zustand는 한 달 전이다.

1년 안에 다운로드 수의 변화도 Zustand는 우상향, recoil은 지지부진..

그 외에도 Zustand의 장점은

  • 리덕스와 유사한 store패턴이다.
  • 보일러플레이트가 없다시피 하다.
  • 러닝커브가 낮다.
  • 리덕스 데브툴 활용이 가능하다
  • swallow를 통해 렌더링을 제한 할 수 있다.
  • 타입스크립트 친화적이다.

Zustand써보기

// store.ts
import { create} from 'zustand'

type CounterStore = {
  count: number
  increment: () => void
  incrementAsync: ()=> Promise<void>;
  decrement: () => void
}

//Best Practice: 어떤 store를 만들던 특정 feature로 그룹핑해라 => 그것만의 store파일을 만들 것. 

export const useCounterStore = create<CounterStore>((set) => ({
  count: 0,
  increment: () => {
    set((state)=>({ count: state.count+1 }))
  },
  incrementAsync: async()=>{
    await new Promise((resolve)=> setTimeout(resolve, 1000))
    set((state)=>({ count: state.count+1 }))
  },
  decrement: () => {
    set((state)=>({ count: state.count-1 }))
  },
}))
import { useCounterStore } from "@/stores/store";
import { useEffect } from "react";

//컴포넌트가 아닌 함수에서 Zustand사용하기 
const setCount=()=>{
  useCounterStore.setState({count:1})
}

const App=()=>{
  const count= useCounterStore((state)=> state.count); //count만 바뀔 때 재렌더링,
  const {count}= useCounterStore((state)=> state); //store안 어떤 state가 바뀌든 재렌더링
  return <OtherComponent count={count} />;
};

type OtherComponentProps = {
  count: number;
};

const OtherComponent= ({count}: OtherComponentProps)=>{
  const increment= useCounterStore((state)=> state.increment);
  const icrementAync= useCounterStore((state)=> state.incrementAsync) //1초뒤 +1
  const decrement= useCounterStore((state)=> state.decrement);

  useEffect(()=>{
    setCount()
  },[])
  return (
    <div>
      {count}
      <div>
      <button onClick={increment}>Increment</button>
      <button onClick={icrementAync}>Decremernt</button>
      <button onClick={decrement}>Decremernt</button>
      </div>
    </div>

  )

};

Best Practice

  1. 컴포넌트에 꼭 필요한 state만 가져오자
 const count= useCounterStore((state)=> state.count); //count만 바뀔 때 재렌더링,
 const {count}= useCounterStore((state)=> state); //store안 어떤 state가 바뀌든 재렌더링

위 예시에서 useCounterStore() 또는 useCounterStore((state)=>state))를 하게 될 경우 모든 state가 리턴되어 컴포넌트에 의존성 주입이되므로 count 이외의 state가 바뀌어도 원치않는 리렌더링이 발생한다.

이를 방지하고자 컴포넌트에 꼭 필요한 state만 가져오도록 (state)=> state.count 처럼 selector function을 사용해 콕 집어 가져오자

profile
Make things

0개의 댓글