[React] TodoList 만들기

SangHun Han·2023년 7월 16일
0
post-thumbnail

📃 TodoList 만들기


📌 만들기 전에...

  • TodoList에 어떤 구현을 하면 좋을까?
  • 구현할 항목들을 어떤식으로 배치하면 좋을까?
  • React로 만들기 위해서 몇 가지의 상태관리 기능이 필요할까?
  • 기능들을 여러가지 훅, 함수들로 어떻게 구현을 진행하면 좋을까?

개인적으로 간단한 토이프로젝트를 진행해보면 좋을 것 같다고 생각해서
가장 처음으로 만들어보는 프로젝트를 "내가 오늘 해야할 일을 어떤식으로 정리해볼까?"라는 생각에 TodoList를 한번 만들어봐야겠다는 생각이 들었다.



👨🏻‍💻 기능 및 메소드별 코드 설명

function App() {
  const [todos, setTodos] = useState([]);
  const [todoText, setTodoText] = useState('');
  const [darkMode, setDarkMode] = useState(false);
  const [today, setToday] = useState('');
};

💡 useState() 상태관리

  • 내가 할 일의 목록을 관리하는 'todos'와 input란에 입력된 텍스트를 관리하기 위해 'todoText'를 useState로 상태 관리를 해준다.
  • 또한, 'darkMode' 상태를 사용하여 다크모드를 토글할 수 있도록 기능을 추가하고 기본값은 false로 다크모드가 적용되지 않았을 때를 지정해주며, 'today'라는 오늘의 날짜를 나타내기 위해 동일하게 useState로 상태 관리를 해준다.

useEffect(() => {
    const currentDate = new Date();
    const formattedDate = currentDate.toLocaleDateString('ko-KR', {
      weekday: 'long',
      year: 'numeric',
      month: 'long',
      day: 'numeric',
    });
    setToday(formattedDate);
  }, []);

💡 useEffect()를 이용한 날짜 기능

  • useEffect 훅을 사용하여 현재 날짜를 가져와 "today"상태인 setToday에 저장을 하고, "toLocalDateString"이라는 메소드로 날짜를 원하는 형식으로 포맷팅한다.
    (포맷팅을 하게되면 날짜를 년/월/일/요일까지 상세하게 나타낼 수 있음)

function addTodo() {
    if (todoText.trim() !== '') {
      setTodos([...todos, { text: todoText, completed: false }]);
      setTodoText('');
   	}
};

💡 appTodo() 함수

  • addTodo 함수를 만들어 input란에 입력된 텍스트가 비어있지 않은 경우에만 새로운 할 일들을 추가한다.
  • 이는 "setTodos"를 이용하여 나열된 "todos" 배열에 새로운 할 일들을 추가한다. (기본값은 할 일을 아직 해결하지 않았다는 false로 지정한다.)
  • "setTodoText"로 input란을 비워둔다.

function toggleComplete(index) {
    const updatedTodos = [...todos];
    updatedTodos[index].completed = !updatedTodos[index].completed;
    setTodos(updatedTodos);
};

💡 toggleComplete() 함수

  • toggleComplete 함수를 만들어 할 일의 완료 여부를 정하는 기능을 만든다.
  • 할 일의 index를 사용하여 "completed" 속성을 반전시켜 할 일을 완료 했는지, 아직 완료하지 못했는지 구분을 시킨다.

function removeTodo(index) {
    const updatedTodos = [...todos];
    updatedTodos.splice(index, 1);
    setTodos(updatedTodos);
};

💡 removeTodo() 함수

  • removeTodo 함수를 만들어 해당 index의 할 일을 제거한다.
  • splice 메소드를 이용하여 배열로 지정된 updatedTodos의 index를 제거해준다.

function toggleDarkMode() {
    setDarkMode(!darkMode);
};

💡 toggleDarkMode() 함수

  • toggleDarkMode 함수를 만들어 다크모드 상태를 토글한다.
  • "setDarkMode"를 사용하여 다크모드 상태를 반전시킨다.
    (즉, 기본값인 false에서 반전시켜 True를 만들면 다크모드 상태가 된다.)

return (
    <div className={`container ${darkMode ? 'dark-mode' : ''}`}>
      <div className='header'>
      <div className='today-date'>{today}</div>
        <h1>My Todo List</h1>
        <div className='dark-mode-toggle'>
          <label htmlFor='darkModeToggle'>다크모드</label>
          <input
            type='checkbox'
            id='darkModeToggle'
            checked={darkMode}
            onChange={toggleDarkMode}
          />
        </div>
      </div>
      <div className='underline'></div>
      <div className='todo-input'>
        <input
          type='text'
          placeholder='할 일을 입력하세요'
          value={todoText}
          onChange={(e) => setTodoText(e.target.value)}
        />
        <button onClick={addTodo}>추가</button>
      </div>
      <ul className='todo-list'>
        {todos.map((todo, index) => (
          <li
            key={index}
            className={todo.completed ? 'completed' : ''}
            onClick={() => toggleComplete(index)}
          >
            {todo.text}
            <button onClick={() => removeTodo(index)}>완료</button>
          </li>
        ))}
      </ul>
      
    </div>
    
  );

💡 return()

  • 체크박스를 통해 다크모드의 유무를 결정하고, 입력 input 필드를 사용하여 할 일을 새롭게 추가할 수 있다.
  • 할 일의 목록은 "todos" 배열의 매핑으로 생성이 되며, 클릭 이벤트로 완료 여부를 결정하고, 완료 버튼을 클릭하면 해당 할 일을 완료 상태로 만들 수 있다.
    (취소선 표시로 할 일을 완료했다는 상태를 나타냄)


🔎 전체 코드

import React, { useState, useEffect } from 'react';
import './App.css';

function App() {
  const [todos, setTodos] = useState([]);
  const [todoText, setTodoText] = useState('');
  const [darkMode, setDarkMode] = useState(false);
  const [today, setToday] = useState('');

  useEffect(() => {
    const currentDate = new Date();
    const formattedDate = currentDate.toLocaleDateString('ko-KR', {
      weekday: 'long',
      year: 'numeric',
      month: 'long',
      day: 'numeric',
    });
    setToday(formattedDate);
  }, []);

  function addTodo() {
    if (todoText.trim() !== '') {
      setTodos([...todos, { text: todoText, completed: false }]);
      setTodoText('');
    }
  };

  function toggleComplete(index) {
    const updatedTodos = [...todos];
    updatedTodos[index].completed = !updatedTodos[index].completed;
    setTodos(updatedTodos);
  };

  function removeTodo(index) {
    const updatedTodos = [...todos];
    updatedTodos.splice(index, 1);
    setTodos(updatedTodos);
  };

  function toggleDarkMode() {
    setDarkMode(!darkMode);
  };

  return (
    <div className={`container ${darkMode ? 'dark-mode' : ''}`}>
      <div className='header'>
      <div className='today-date'>{today}</div>
        <h1>My Todo List</h1>
        <div className='dark-mode-toggle'>
          <label htmlFor='darkModeToggle'>다크모드</label>
          <input
            type='checkbox'
            id='darkModeToggle'
            checked={darkMode}
            onChange={toggleDarkMode}
          />
        </div>
      </div>
      <div className='underline'></div>
      <div className='todo-input'>
        <input
          type='text'
          placeholder='할 일을 입력하세요'
          value={todoText}
          onChange={(e) => setTodoText(e.target.value)}
        />
        <button onClick={addTodo}>추가</button>
      </div>
      <ul className='todo-list'>
        {todos.map((todo, index) => (
          <li
            key={index}
            className={todo.completed ? 'completed' : ''}
            onClick={() => toggleComplete(index)}
          >
            {todo.text}
            <button onClick={() => removeTodo(index)}>완료</button>
          </li>
        ))}
      </ul>
      
    </div>
    
  );
}

export default App;


👀 결과 화면

TodoList를 실행했을 때, 기존 화면 결과에서는 다크모드가 적용되지 않은 상태에서 현재 날짜와 요일, 할 일을 입력하는 칸과 추가 버튼, 할 일을 마쳤을 때의 결과와 완료 버튼이 나타난다.

다크모드가 적용 된 상태에서는 기존 화면과는 달리 화면이 어두워지며, 글자의 색은 흰색으로 배경색과 정반대가 된다.




🤔 다크 모드를 만들기 위해서는 어떤 고민을 했는가?

여러 가지 기능들을 추가해보기 위해서 "다크 모드" 기능을 넣어보면 좋겠다! 라고 생각해서
"그럼 다크 모드 기능을 어떤식으로 만들어야 할까?"를 많이 고민했었다.

🙄 처음에는...

그냥 CSS 파일에 다크 모드 색 구현해주고, HTML에 토글 버튼 구조맞춰서 적용시켜주면 되지않나..

이렇게만 생각하면서 너무 간단하게 해결 할려고 했다.
"JavaScript와 React를 이용하여 구현하면, 내가 공부하는 과정에서 더 많은 도움이 될 수 있지 않을까?"라는 깨달음을 얻었다.

🧐 이렇게 해볼까??

CSS 파일에 다크 모드 색을 구현해주고, JavaScript에서는 클릭 이벤트를 이용해서 다크 모드의 유무를 바꿔가며 동작해보며 React에서는 다크 모드 관련 함수를 따로 만들어서 return값으로 다크 모드 버튼을 구현하여 만들어보자!

많은 고민을 하다가 좀 더 어렵고, 복잡하게 구현해야 공부를 할 수 있다고 생각했기 때문에
React로 다크 모드를 구현했다.




🛠️ 리팩토링

일단 만드는 것은 달성했으니 이제 코드를 깔끔하게 정리하여 효율을 높이는 일이 남았다.

개선 예정

  • 할 일을 나타낸 내용을 직접적으로 화면에서 삭제하는 기능 추가
  • 할 일을 체크박스로 표시하여 구분하기 쉽게 정리
  • CSS 마크업 개선
profile
매일매일 성장하는 개발자 🚀

0개의 댓글