[React] Zustand 요약

Jayden ·2024년 6월 5일

1. Zustand

  • 독일어로 "상태"라는 의미를 가지고 있다.
  • Flux 패턴 기반이다.
  • Redux, Recoil 등과 다르게 provider로 래핑할 필요가 없다.

1) 기본 구조

Redux와 다르게 Action과 State를 일괄적으로 store에 정의해서 사용한다.

import { create } from 'zustand'

const useStore = create((set) => ({
  count: 1, // State
  inc: () => set((state) => ({ count: state.count + 1 })), // Action
}))

function Counter() {
  const { count, inc } = useStore()
  return (
    <div>
      <span>{count}</span>
      <button onClick={inc}>one up</button>
    </div>
  )
}

2) 상태값 변경

import { create } from 'zustand'

const useCountStore = create((set) => ({
  count: 0,
  inc: () => set((state) => ({ count: state.count + 1 })),
}))

상태를 병합할 경우, 다음과 같이 스프레드 연산자를 사용해야 하지만 생략 가능하다

set((state) => ({ ...state, count: state.count + 1 })) 

( = 동일한 의미)

set((state) => ({ count: state.count + 1 }))
  • 중첩 객체 상태를 변경할 경우
import { create } from 'zustand'

const useCountStore = create((set) => ({
  nested: { count: 0 },
  inc: () =>
    set((state) => ({
      nested: { ...state.nested, count: state.nested.count + 1 },
    })),
}))

위의 예제는 nested라는 상태값에 { count : 0 } 이라는 객체가 들어가 있다. 이럴 경우에는 스프레드 연산자를 사용하여 상태값을 설정해 주어야한다.

3) 상태값 구독

다음과 같은 스토어가 있다고 가정해 보겠습니다.

import create from 'zustand';
import { shallow } from 'zustand/shallow';

// 상태 스토어 생성
const useStore = create((set) => ({
  cidar: 0,
  cola: 0,
  increaseCider: () => set((state) => ({ cider : state.cider + 1 })),
  increaseCola: () => set((state) => ({ cola: state.cola + 1 })),
  resetAll: () => set({ cola: 0, cider: 0 })
}));

export default useStore;

다른 컴포넌트에서 상태값 구독

export default function Cider() {

	const cidar = useStore((state) => state.cidar);
  
  	console.log(cider); 
}

export default function Cola() {

	const cola = useStore((state) => state.cola);
  
  	console.log(cola); 
}
  • 다중 상태값 구독

객체 형태로 값을 가져올때는 불필요한 렌더링이 발생하므로 zustand에서 제공하는 useShallow 함수로 구독한 값이 변경될 경우에만 렌더링 되도록 적용해야 합니다.


import { useShallow } from 'zustand/react/shallow'

export default function Cider() {

const { cidar, increaseCider } = useStore(useShallow((state) => 

({ cidar: state.cidar, increseCider: state.increseCider })));	
  
 	console.log('Cider 컴포넌트 렌더링');
 
  	return(
     	<button onClick={increseCider}>사이다 추가</button> 
    )
}
import { useShallow } from 'zustand/react/shallow'

export default function Cola() {

  	const { Cola, increaseCola } = useStore(useShallow((state) => 
    ({ cola: state.cidar, increseCola: state.increaseCola })));	
  
  	console.log('Cola 컴포넌트 렌더링');
  
  	return(
     	<button onClick={increseCola}>콜라 추가</button> 
    )
}
profile
프론트엔드 개발자

0개의 댓글