React_06_todoList

송지윤·2024년 6월 7일

React

목록 보기
6/15

src/todoList/TodoList.js
할 일 추가하기

import { useState } from "react";

/*
    React 에서 꼭 지켜야하는 개념
    불변성을 유지해야함. (얕은 복사 이유)
    immutability
    : 데이터 구조(ex. 배열, 객체 등)의 원본값을 변경할 수 없는 성질을 의미함.
    -> 불변성을 유지한다는 것은 한 번 설정된 초기값을 가진 데이터 구조를 직접 변경하지 않고,
    항상 새로운 데이터 구조를 생성해서 업데이트하는 것을 뜻함

    왜? React는 상태변화가 일어날 때 효율적으로 컴포넌트를 리렌더링하기 위해
    상태의 불변성을 가정한다.
    불변성을 유지하면 이전 상태와 새로운 상태가 다르다는 것을 쉽게 알 수 있으며,
    이를 통해서 변경된 부분만 업데이틑 할 수 있는 것.
*/

function TodoList() {

    // 상태
    const [todos, setTodos] = useState([{title : "React 복습하기", isDone : false},
        {title : "일기쓰기", isDone : true}]);

    const [inputValue, setInputValue] = useState('');

    // 함수
    // 할 일 추가 함수
    const handleAddTodo = () => {
        // 기존의 todos 배열과 새로운 할 일 객체를 이어붙여서 새로운 배열을 만든 후,
        // 이를 setTodos 함수를 사용하여 업데이트함.
        // 전개 연산자 => 얕은 복사
        setTodos([...todos, {title : inputValue, isDone : false}]);
        setInputValue(""); // 입력 필드에 있는 값 비워주기
    }

    // 할 일 삭제 함수
    const handleDeleteTodo = (index) => {
        // 함수 호출할 때 넘겨준 index 를 받아줘야함
        // 기존 배열 모양 그대로 복사할 거
        // 얕은 복사 방법 1번째 : slice() 이용 - 원본 배열을 변경하지 않고, 새로운 배열을 반환
        const newTodos = todos.slice(); // 기존의 todos 배열을 복사하여 새로운 배열을 생성

        newTodos.splice(index, 1);
        // splice() : 배열의 기존 요소를 삭제 [추가 또는 교체]
        // splice(start, deleteCount, [item1, item2...])
        // start : 배열에서 변경을 시작할 인덱스
        // deleteCount : 배열에서 제거할 요소의 수
        // [item1, item2...] : 옵션 배열에 추가할 요소들
        setTodos(newTodos);
    }

    // 할 일 완료, 미완료 토글 함수
    const handleToggleTodo = (index) => {
        // todos 안에 있는 isDone 바꿔줘야함
        // 얕은 복사 이용해서 바꿔줘야함
        // 얕은 복사 방법 2 번째 : 전개 연산자(spread operator)
        // - 배열이나 객체의 모든 요소를 개별적으로 펼쳐서 새로운 배열이나 객체를 생성할 때 사용
        const newTodos = [...todos];

        // 해당 인덱스의 todo 항목의 isDone 값을 반전
        newTodos[index].isDone = !newTodos[index].isDone;
        // -> true 면 false, false 이면 true 로 바꿔줌

        // 새로운 배열로 상태를 업데이트
        setTodos(newTodos);
    }

    // return () : 화면에 렌더링할 jsx 작성 구문
    return (
        <div>
            <h1>Todo List</h1>
            <input value={inputValue} onChange={(e) => setInputValue(e.target.value)}/>
            <button onClick={handleAddTodo}>추가하기</button>

            <ul>
                {/* map 이용 배열 값 return */}
                {
                    todos.map((todo, index) => (
                        // 첫번재 todo는 React 복습하기
                        // 두번째 todo는 일기쓰기
                        // 배열에는 요소 번호가 있음
                        // 첫번째는 0, 두번째는 1 index 로 들어옴
                        // return 구문 작성해줘야 화면에 렌더링 됨
                        // 중괄호로 jsx 구문 열었을 때 return 구문 꼭 필요함
                        // return 쓰기 실으면 => 다음에 () 소괄호 작성하고 jsx 문법 작성
                        // -> 중괄호와 return 생략한 것과 같음
                        // return (
                        //     <li>
                        //         <span>{todo.title}</span>
                        //     </li>
                        // );
                        <li>
                            <span style={{textDecoration : todo.isDone ? 'line-through' : 'none'}}>
                                {/* style 안에 중괄호 두번 */}
                                {todo.title}
                            </span>

                            <button onClick={() => handleToggleTodo(index)}>{todo.isDone ? '미완료' : '완료'}</button>
                            <button onClick={() => handleDeleteTodo(index)}>삭제</button>
                            {/* 클릭할 때 index를 handleDeleteTodo함수에 넘겨줌 */}
                        </li>
                    ))
                }
            </ul>
        </div>
    );
}

export default TodoList;

App.js

import logo from './logo.svg';
import './App.css';
import TodoList from './todoList/todoList';

function App() {
  return (
    <div className="App">
      <TodoList />
    </div>
  );
}

export default App;

0개의 댓글