React 연습_3

송지윤·2025년 12월 16일

React

목록 보기
10/15

ToDoList

ToDoList.js

src/toDoList/ToDoList.js

import { useState } from "react";

function ToDoList() {
    // ToDoList에 있어야하는 것
    // 내용 추가, 완료 여부, 삭제
    // ToDoList 값
    // const [toDos, setToDos] = useState([{content : '', isDone : false}]);
    const [toDos, setToDos] = useState([]);
    // 해야할 일 내용과 완료 여부가 배열 형태로 있을 거

    // 내용 삽입할 값
    const [inputValue, setInputValue] = useState('');
    // 빈 값 초기화

    // 수정 중인 값
    const [editToDo, setEditToDo] = useState(null);

    // 할 일 추가 버튼을 누르면 list에 할 일이 추가돼야함
    const handleAddToDo = () => {
        // input 값이 빈 값이면 return
        if(inputValue.trim() === "") return;

        // setToDos([...toDos, {content : inputValue, isDone : false}]);
        setToDos(prev => [
            ...prev,
            {content : inputValue, isDone : false}
        ]);
        
        setInputValue("");
        // input 태그 입력한 값은 초기화 시켜주고 기존에 있던 toDos 배열 아래로 content 쌓아줌
    }

    // 할 일 완료, 미완료 토글 함수
    const handleToggleToDo = (index) => {
        // 배열 번호가 있어야 선택한 줄만 완료, 미완료 가능
        const newToDos = [...toDos];
        // newToDos 에 배열 복사
        newToDos[index].isDone = !newToDos[index].isDone;
        // 선택된 행의 isDone 여부를 반대로 뒤집어줌 false, true

        setToDos(newToDos);
    }

    // 할 일 삭제 함수
    const handleDeleteToDo = (idx) => {
        const newToDos = toDos.slice();
        // 배열 복사 [...toDos] 와 같음
        newToDos.splice(idx, 1);
        // splice() : 배열의 기존 요소를 삭제 [추가 또는 교체]
        // splice(start,deleteCount, [item1, item2...])
        // start : 배열에서 변경을 시작할 인덱스
        // deleteCount : 배열에서 제거할 요소의 수
        // [item1, item2 ...] : 옵션 배열에 추가할 요소들
        setToDos(newToDos);
    }

    // 할 일 수정 버튼 클릭 시
    const handleEditToDo = (index) => {
        setInputValue(toDos[index].content);
        setEditToDo(index); // 수정할 toDo index 번호 담아두기
    }

    // input 박스 옆 수정하기 버튼 클릭 시
    const handleModifyToDo = () => {
        // prev == 이전 상태를 의미
        // prev == 현재 toDos 값
        setToDos(prev =>
            prev.map((toDo, i) =>
                i === editToDo
                    ? {...toDo, content : inputValue, isDone : false}
                    : toDo
            )
        );
        // ...toDo 복사한 객체에서 content 내용과 isDone false로 덮어쓰기
        setEditToDo(null); // 수정된 후 값 비워주기
        setInputValue(""); // input box 값 비워주기
    }

    return (
        <div>
            <h1>To Do List</h1>
            <input value={inputValue} onChange={(e) => setInputValue(e.target.value)}></input>
            <button onClick={editToDo === null ? handleAddToDo : handleModifyToDo}>
                {editToDo === null ? "추가하기" : "수정하기"}
            </button>
            {/* inputValue 에 입력된 값을 담아주고 추가하기 클릭하면 toDos의 content에 들어감 */}
            {/* 수정하기 눌러서 inputValue가 올라온 거면 추가하기 버튼이 수정하기로 바뀜 */}
            <ul>
                {
                    toDos.map((toDo, index) => (
                        <li>
                            <span style={{textDecoration : toDo.isDone ? 'line-through' : 'none'}}>
                                {/* toDo isDone이 true 이면 중간에 줄 */}
                                {toDo.content}
                            </span>

                            <button onClick={() => handleToggleToDo(index)}>{toDo.isDone ? '미완료' : '완료'}</button>
                            {/* true 이면 버튼 text 미완료, false이면 버튼 text 완료 */}
                            <button onClick={() => handleEditToDo(index)}>수정</button>
                            <button onClick={() => handleDeleteToDo(index)}>삭제</button>

                        </li>
                    ))
                }
            </ul>
        </div>
    );
}

export default ToDoList;

App.js

import './App.css'; // light, dark 테마 css 정의돼있음
import ToDoList from './toDoList/ToDoList';

function App() {
  return (
    <div className='App'>
      <ToDoList />
    </div>
  );
}

export default App; // 내보내기

0개의 댓글