Dandy Now!
  • [React.js] 간단한 Todo List 만들기(Zustand를 이용한 전역 상태 관리)
    2024년 02월 13일 11시 10분 11초에 업로드 된 글입니다.
    작성자: DandyNow
    728x90
    반응형

    1. Zustand를 적용한 Todo List

    [그림 1]과 같이 Zustand를 이용해 간단한 Todo List를 구현해 보았다. Zustand를 이용할 경우 Redux보다 훨씬 간편하게 전역 상태를 관리할 수 있었다. 전역 상태를 이용해야 하는 컴포넌트에서 Zustand의 create 메서드를 이용해 작성한 모듈을 로딩하기만 하면 즉시 사용할 수 있었기 때문이다.

    [그림 1] 완성된 Todo List

     

    2. React.js 프로젝트 생성

    "react-zustand-todolist"라는 리액트 프로젝트를 생성한다.

    npx create-react-app react-zustand-todolist

     

    3. Zustand 라이브러리 설치

    npm i zustand

    😉 공식 문서 : https://docs.pmnd.rs/zustand/getting-started/introduction

     

    4. Zustand 적용

    📌 store.js

    store.js의 useStore를 import 하기만 하면 어떤 컴포넌트에서도 create 메서드가 반환한 객체의 속성을 공유(전역 상태 관리)할 수 있다.

    // src/store.js
    
    import { create } from "zustand";
    
    // zustand의 create 메서드를 이용해서 상태를 관리한다.
    // todos는 Todo List의 상태 값을 가지고 있는 배열이다.
    // addTodo, makeDone을 이용해 todos 값을 변경한다.
    const useStore = create((set) => ({
      todos: [],
      addTodo: (todo) => set((state) => ({ todos: [...state.todos, todo] })),
      makeDone: (id) =>
        set((state) => ({
          todos: [
            ...state.todos.map((el) => {
              if (el.id === id) {
                return { ...el, done: !el.done };
              }
              return { ...el };
            }),
          ],
        })),
    }));
    
    export default useStore;

     

    📌 TodoInput.js

    // src/TodoInput.js
    
    import { useState } from "react";
    import useStore from "./store"; // Zustand 로딩
    
    function TodoInput() {
      const [newTodo, setNewTodo] = useState("");
    
      const addTodo = useStore((state) => state.addTodo); // addTodo 메서드 사용
      const handleAddTodo = () => {
        if (newTodo) {
          addTodo({
            id: Date.now(),
            text: newTodo,
            done: false,
          });
          setNewTodo("");
        }
      };
      return (
        <div>
          <input
            type="text"
            value={newTodo}
            onChange={(e) => setNewTodo(e.target.value)}
          />
          <button onClick={handleAddTodo}>Add</button>
        </div>
      );
    }
    
    export default TodoInput;

     

    📌 TodoList.js

    // src/TodoList.js
    
    import useStore from "./store"; // Zustand 로딩
    
    function TodoList() {
      const { todos, makeDone } = useStore((state) => state); // todos 속성, makeDone 메서드 사용(구조 분해 할당하였음)
      console.log(todos);
      const handleDone = (id) => {
        makeDone(id);
      };
      return (
        <>
          <ul style={{ listStyle: "none" }}>
            {todos.map((el) => (
              <li
                key={el.id}
                onClick={() => {
                  handleDone(el.id);
                }}
              >
                {el.done && <del>{el.text}</del>}
                {!el.done && el.text}
              </li>
            ))}
          </ul>
        </>
      );
    }
    
    export default TodoList;

     

    📌 App.js

    // src/App.js
    
    import "./App.css";
    import TodoInput from "./TodoInput";
    import TodoList from "./TodoList";
    
    function App() {
      return (
        <div className="App">
          <h1>Zustand Todo List</h1>
          <div>
            {/* 위에서 생성한 컴포넌트 적용 */}
            <TodoInput />
            <TodoList />
          </div>
        </div>
      );
    }
    
    export default App;
    728x90
    반응형
    댓글