[Zustand] React 상태관리 라이브러리

윤후·2023년 4월 7일
1

Zustand

목록 보기
1/1

이전엔 Redux(Tool-kit)을 사용하면서 다른 상태관리를 사용해본적은 없었다. 하지만 이번 프로젝트를 진행하면서 Zustand라는 상태관리 라이브러리를 사용해 봤는데 보일러플레이트 코드가 길지 않아서 좋았고, 무엇보다 너무 편하게 사용할 수 있어서 좋았다.

최소한의 코드로 상태를 변경할 수 있고, 어떻게 변하는지만 직관적으로 알면 좋았던 Zustand에 대한 기본적인 문법과 사용법을 기록해두려한다.

Zustand


"Zustand"는 독일어로 상태라는 뜻이다. 이 라이브러리의 특징은 위에서 이야기 했듯 사용하기 간편하고 굉장히 쉽다는 것이다. 보일러플레이트가 필요없다 싶을 정도로 간편하다.

설치

공식 Zustand

npm install zustand # or yarn add zustand

사용법

// store.module.ts

// js로 사용할 때.
import {create} from 'zustand'

export const projectName = create((set) => ({
 	state: 0,
  	setState: (newState) => set({state: newState})
}))

// ts로 사용할 때.
interface State1 {
	state: number
  	setState: (newState: number) => void
}

export const projectName = create<State1>((set) => ({
	state: 0,
  	setState: (newState) => set({state: newState})
}))

위의 방법이 아주 기본적인 사용이 되겠다. 아주 쉽게 store에 state를 만들었고, 이제 사용만 하면 되는것이다.

// Test.tsx

import { projectName } from './store.module'

const Test = () => {
	const { state, setState } = projectName()
    
    return (
    	<div>{state}</div>
    )
}

React에서 사용하는 방법을 예로 들었다. store.module.ts에서 export한 상태를 가져와 객체의 구조분해할당으로 가져오면 되겠다.

끝이다. 이렇게 쉽게 접근할 수 있는 상태관리가 있었는가..Redux를 사용했다면 Zustand보다 더 많은 코드들을 정리하고 관리했어야 했을것이다.

응용

공식문서에 있는것과 같이 간단한 todo list를 관리하는 state를 작성해보자.

// store.module.ts

interface TodoState {
	id: string
  	description: string
  	completed: boolean
}

interface TodoListState {
	todos: TodoState[]
  	addTodo: (description: string) => void
}

export const useTodo = create<TodoListState> = ((set) => ({
	todos: []
  	addTodo: (description) => {
  		set((prevState) => ({
        	todos: [
            	...prevState.todos, {
                	id: Math.random().toString(36).substring(2,11),
					description,
                  	completed: false
                }
            ]
        })
    )}
}))


// Test.tsx

import { useTodo } from './store.module'

interface TestProps {
	description: string
}

const Test: React.FC<TestProps> = ({description}) => {
	const { todos, addTodo } = useTodo
    
    return (
    	<div>
      		<button onClick={() => addTodo(description)}>Add Todo</button>
      	</div>
    )
}

// button을 누르면 addTodo가 실행되는것을 볼 수 있다.

위의 예제처럼 콜백함수로 prevState를 넘겨주고 todos를 추가하는 방식으로 코드를 만들 수 있겠다.

사실 위의 store.module.ts에서 state의 구조를 모두 만들고 사용할 수 있겠지만, 다르게 사용해도된다.

// store.module.ts

interface TodoState {
	id: string
  	description: string
  	completed: boolean
}

interface TodoListState {
	todos: TodoState[]
  	addTodo: (newTodos: TodoState[]) => void
}

const useTodo = create<TodoListState>((set) => {
	todos: [],
  	addTodo: (newTodos: TodoState[]) => set({todos: newTodos})
})
// test.tsx

import { useTodo } from './store.module'

interface TestProps {
	description: string
}

const Test: React.FC<TestProps> = ({description}) => {
  const { todos, addTodo } = useTodo
  
  const onClickAdd = () => {
  	const copyTodos = [...todos]
    copyTodos.push({
      id: Math.random().toString(36).substring(2,11),
      description,
      completed: false
    })
    addTodo(copyTodos)
  }
    
  return (
    <div>
    	<button onClick={() => onClickAdd()}>Add Todo</button>
	</div>
	)
}

// button을 누르면 addTodo가 실행되는것을 볼 수 있다.

이번 방법은 store.module.ts에서 prevState를 넘겨주는게 아닌 새로운 newTodos를 만들고 해당 배열을 새롭게 써주는 형식인 것이다.

나는 이 두가지 방법을 많이 사용했었다. 컴포넌트의 코드를 좀 더 짧게 사용하기 원한다면 위의 방법을 사용해도 되겠지만, 아래의 방법을 사용하기에도 좋은 방법이될 수 있겠다.

개인적으로 Redux보다 좀 더 쓰기 편하고 보일러 플레이트도 적어 사용하기 너무 편했던 상태관리 라이브러리다.

참고

공식문서
TOAST UI

profile
궁금한걸 찾아보고 공부해 정리해두는 블로그입니다.

0개의 댓글