본문 바로가기

공부일지/React

비전공자의 공부일지 - Zustand 맛보기

728x90
반응형

Zustand란??

 

Zustand는 간단한 상태관리 솔루션이라고 한다.

Zustand는 독일어로 State(상태)를 뜻하고 Jotai 및 React 스프링 개발자가 구축한 빠르고 확장 가능한 상태 관리 솔루션이다.

 

보일러 플레이트를 많이 최소화시켰다고 한다.

  • 상용구 코드 감소
  • Zustand는 상태 값이 변경될 때만 구성 요소를 렌더링 하고 구성 요소를 다시 렌더링 하지 않고도 상태 변경을 처리할 수 있는 경우가 많다.
  • 상태 관리는 중앙 집중식이며 단순하게 정의된 작업을 통해 업데이트된다. 이 부분에서 Redux와 유사하지만 개발자가 상태를 처리하기 위해 Reducer, Action 및 Dispatch를 만들어야 하는 Redux와 달리 Zustand는 훨씬 쉽다.
  • Hooks를 상용하여 상태를 상용한다.
  • 컨텍스트 제공을 사용할 필요가 없어 깨끗한 코드를 제공하므로 코드가 더 짧고 가독성이 높다.

 

간단한 카운터앱 만들기

 

Store.js

import { create } from "zustand";

export const useCounterStore = create((set) => ({
  count: 1,
  increment: () => set((state) => ({ count: state.count + 1 })),
  reset: () => set({ count: 1 })
}));

 

Counter.js

import React from "react";
import { useCounterStore } from "../store";

const Counter = () => {
  const { count, increment, reset } = useCounterStore();
  return (
    <div>
      <p>{count}</p>
      <button onClick={increment}>one up</button>
      <button onClick={reset}>reset</button>
    </div>
  );
};

export default Counter;

 

App.js

import Counter from "./components/Counter";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <header className="App-header">
        <Counter />
      </header>
    </div>
  );
}

코드를 보면 store에 필요한 데이터를 작성하고 그에 맞는 이벤트들을 set으로 가져와서 작업 처리하는 방식이다.

사용할 때도 필요한 요소만 불러와서 count increment, reset을 가져와서 onClick에 넣어서 사용하면 된다.

어떻게 보면 내가 필요한 이벤트와 데이터를 작성하고 그에 맞는 것만 불러와서 사용가능 하니 사물함에서 필요한 것만 뽑아서 사용하는 느낌이 든다.

 

이번에도 Todo를 만들었다.

 

TodoListStore.js

import { create } from "zustand";

export const useTodoStore = create((set) => ({
  todos: [],
  addTodo: (todoText) =>
    set((state) => ({
      todos: [
        ...state.todos,
        {
          text: todoText,
          id: getId(),
          isCompleted: false
        }
      ]
    })),
  deleteTodo: (todoId) =>
    set((state) => ({
      todos: state.todos.filter((todo) => todo.id !== todoId)
    })),
  completeTodo: (todoId) =>
    set((state) => ({
      todos: state.todos.map((todo) => {
        if (todo.id === todoId) {
          return {
            ...todo,
            isCompleted: true
          };
        }
        return todo;
      })
    }))
}));

let id = 0;
function getId() {
  return id++;
}

기존에 사용하던 코드와 크게 다를 건 없는 거 같다.

set을 사용해서 todos에 바로 데이터를 입력하는 거 정도만 살짝 다른 거 같다. 

삭제는 filter를 사용해서 id와 다른 것들만 return 되게 하였다.

 

 

TodoList.js

import React, { useState } from "react";
import { useTodoStore } from "../store/useTodoStore";

const TodoList = () => {
  const { todos, addTodo, deleteTodo, completeTodo } = useTodoStore();
  const [todoValue, setTodoValue] = useState("");
  const handleSubmit = (e) => {
    e.preventDefault();
    addTodo(todoValue);
    setTodoValue("");
  };
  return (
    <div>
      <h3>Todo App</h3>
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          id="new-todo"
          name="newTodo"
          value={todoValue}
          onChange={(e) => setTodoValue(e.target.value)}
        />
        <button type="submit">Add</button>
      </form>
      <ul>
        {todos.map((todo) => (
          <li key={todo.id}>
            <span
              style={{
                textDecoration: todo.isCompleted ? "line-through" : "unset"
              }}
            >
              {todo.text}
            </span>
            {!todo.isCompleted ? (
              <button onClick={() => completeTodo(todo.id)}>✅</button>
            ) : null}
            <button onClick={() => deleteTodo(todo.id)}>❌</button>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default TodoList;

 

항상 해오던 방식이라 한번 보면 이해가 될 것 같다.

input에 value값을 state에 저장하고 그 값을 스토어에 보내고 스토어에서 판단하고 저장하고 하는 방식이다.

삭제나 완료는 id값을 onClick으로 전달해서 store에서 판단하고 작업한다.

 

확실히 BE보단 FE쪽이 다양하고 많아서 알아야 될 것도 많은 것 같다.

회사에서 어떤 방식을 사용하는지에 따라 그 방식에 적응을 해야 되니 그래도 배울게 많다는 점과 작업한 내용이 우리 눈에 바로 보인다는 게 좋은 거 같다.

 

728x90
반응형