React를 이용하여 TODO LIST만들기

혼빈·2024년 9월 25일

오늘은 TODO LIST를 만들어보겠습니다.

우선 React를 사용하기 위한 기초작업으로
html에서는 사용할 UI와 테일윈드를 불러왔구 div root를 만들어놨습니다.

<!-- 데이지 UI 불러오기  -->
<link href="https://cdn.jsdelivr.net/npm/daisyui@4.5.0/dist/full.min.css" rel="stylesheet" type="text/css" />

<!-- 테일윈드 불러오기 -->
<script src="https://cdn.tailwindcss.com"></script>

<div id="root"></div>

JS에서는 React를 사용하기 위해서 불러와줬구요

import React, { useState } from "https://cdn.skypack.dev/react@18";
import ReactDOM from "https://cdn.skypack.dev/react-dom@18";

이 아래로 본격적인 코딩을 해보겠습니다.


const TodoWriteForm = ({ addTodo: _addTodo }) => {
  const [newTodoTitle, setNewTodoTitle] = useState("");

  const addTodo = () => {
    if (newTodoTitle.trim().length == 0) return;
    _addTodo(newTodoTitle);
    setNewTodoTitle("");
  };

  return (
    <>
      <div className="flex gap-x-3">
        <input
          className="input input-bordered"
          type="text"
          placeholder="할 일 써"
          value={newTodoTitle}
          onChange={(e) => setNewTodoTitle(e.target.value)}
        />
        <button className="btn btn-primary" onClick={() => addTodo()}>
          할 일 추가
        </button>
      </div>
    </>
  );
};

const TodoListItem = ({
  index,
  todos,
  todo,
  removeTodo: _removeTodo,
  modifyTodo: _modifyTodo
}) => {
  const [inputNumberValue, setInputNumberValue] = useState(todo);
  const [editModeStatus, setEditModeStatus] = useState(false);
  const removeTodo = () => {
    _removeTodo(index);
  };

  const modifyTodo = () => {
    _modifyTodo(inputNumberValue, setEditModeStatus, index);
  };

  const editView = (
    <>
      <input
        type="text"
        placeholder="할일 입력"
        value={inputNumberValue}
        onChange={(e) => setInputNumberValue(e.target.value)}
      />
      &nbsp;
      <button className="btn btn-success" onClick={modifyTodo}>
        수정 완료
      </button>
      &nbsp;
      <button
        className="btn btn-warning"
        onClick={() => setEditModeStatus(false)}
      >
        수정 취소
      </button>
    </>
  );

  const readView = (
    <>
      <button className="btn btn-info" onClick={() => setEditModeStatus(true)}>
        수정
      </button>
    </>
  );

  return (
    <>
      <li className="flex items-center gap-x-3 mb-3" key={index}>
        <span>
          {index + 1}번 째 할일 : {todo}
        </span>
        <button className="btn btn-error" onClick={removeTodo}>
          삭제
        </button>

        {editModeStatus ? editView : readView}
      </li>
    </>
  );
};

const TodoList = ({ todos, removeTodo, modifyTodo }) => {
  return (
    <>
      <div>
        {todos.length == 0 ? (
          <h4>님 할일 없음????</h4>
        ) : (
          <>
            <h4>새 할일</h4>
            <nav>
              <ul>
                {todos.map((todo, index) => (
                  <TodoListItem
                    index={index}
                    todos={todos}
                    todo={todo}
                    removeTodo={removeTodo}
                    modifyTodo={modifyTodo}
                  />
                ))}
              </ul>
            </nav>
          </>
        )}
      </div>
    </>
  );
};

const App = () => {
  const [todos, setTodos] = useState([]);

  const addTodo = (newTitle) => {
    if (newTitle.trim().length == 0) return;
    setTodos([...todos, newTitle.trim()]);
  };

  const removeTodo = (index) => {
    const newTodos = todos.filter((_, _index) => index != _index);
    setTodos(newTodos);
  };

  const modifyTodo = (inputNumberValue, setEditModeStatus, index) => {
    setTodos(
      todos.map((_todo, _index) =>
        _index === index ? inputNumberValue : _todo
      )
    );
    setEditModeStatus(false);
  };

  return (
    <>
      <TodoWriteForm addTodo={addTodo} />
      <hr />
      <TodoList todos={todos} removeTodo={removeTodo} modifyTodo={modifyTodo} />
    </>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
  • 실행하는 App에서 글쓰기와 LIST를 컴포넌트로 분리시켜서 코딩을 해봤습니다.
  • 처음에 만들때는 컴포넌트 분리안하고 App안에 그대로 쭉 코딩을 하고 그 후에 컴포넌트로 분리를 하였습니다. 중요 데이터에 직접적인 간섭이 되지않게 하는게 정말 중요하다고 생각을 하기때문에 이렇게 해봤어요

  • React를 이용해서 JS안에 만들면서 느낀건데 이것만 능숙하게 잘 이용한다면 다른 부분에서도 유용하게 활용할수있다고 생각이 들더라고요 나중에 스프링환경에서도 Controller에 부담도 줄일수있을거 같구요

아래는 실행화면입니다.

다음에는 기능뿐만 아니라 좀 더 이쁘게 꾸면서 그럴싸하게 만들어보겠습니다 ~

profile
코딩중

0개의 댓글