TIL #22 입문주차 개인과제-2

DO YEON KIM·2024년 5월 16일
0

부트캠프

목록 보기
22/72

하루 하나씩 작성하는 TIL #22


지난 번 3번을 이어서 작성하겠다.


3. Todo 추가하기 구현하기

useState 를 이용해서 todo 상태를 정의합니다.
추가하기 버튼 클릭 시 Working 파트로 투두 카드가 추가됩니다.

이전 과제에서 객체명 일부를 바꿔줘 가면서

사용한 hook은 오직 useState
기능 구현을 위해 생성한 함수는 2개 입니다. onChangeHandler , onSubmitHandler
사용한 javascript 내장 메서드는 map, filter 입니다.
todo의 initial state는 {id: 0, title: “”, body: “”, isDone: false} 입니다.


function App() {
  const [todos, setTodos] = useState([]);
  const [title, setTitle] = useState('');
  const [body, setBody] = useState('');

App이라는 이름의 함수형 컴포넌트를 정의해준다.

useState 훅을 사용하여 3가지 상태 변수를 선언해준다.

todos는 할 일 목록을 저장하며, 초기 값은 빈 배열로 해준다.
title과 body는 제목과 내용을 저장하며 초기 값은 빈 문자열이다.


  const onChangeTitle = (e) => setTitle(e.target.value);
  const onChangeBody = (e) => setBody(e.target.value);

두 개의 이벤트 핸들러 함수를 정의해준다.
입력 필드의 값이 변경될 때 호출되며, title과 body에 각각 설정한다.

target.value는 React에서 폼 입력요소의 값을 읽어오기 위해 자주 사용하는 속성 중 하나다. 이는 이벤트가 발생한 dom요소를 가리킨다.


  const onSubmitHandler = (e) => {
    e.preventDefault();
    if (title.trim() === '' || body.trim() === '')
      return;
    
    const newTodo = {
      id: Date.now(),
      title,
      body,
      isDone: false,
    };
    
    setTodos([...todos, newTodo]);
    setTitle('');
    setBody('');
  };

    

폼이 제출될 때 (=작성하기 버튼) 호출되는 함수를 정의한다.
e.preventDefault();를 사용하여 폼의 기본 제출 동작을 막아준 후, title 또는 body가 비어있으면 함수를 종료한다.

trim()은 문자열에서 양쪽 끝에 있는 공백만 제거하며, 중간에 있는 공백은 제거하지 않는다. 불필요한 공백을 제거하기 위해 사용한다.

id는 현재 시간을 밀리초 단위로 반환해주는 함수를 사용하여 고유한 식별자로 설정하고, title과 body는 현재 상태에서 가져와준다.

isDone은 false로 초기화하여 새로운 할 일이 아직 완료되지 않았음을 나타내준다.

setTodos를 호출하여 새로운 할 일을 기존 할 일 목록에 추가해준다.
기존 todos 배열을 복사하고, 새 할 일 newTodo를 배열에 추가해준다.
setTitle과 setBody를 호출하여 입력 필드를 초기화해준다.


  const onDeleteHandler = (id) => {
    setTodos(todos.filter((todo) => todo.id !== id));
  };

삭제하는 함수

setTodos를 호출하여 todos 배열에서 id가 일치하지 않는 항목들만 남긴다. (= 일치하는 항목은 삭제)


  const onToggleHandler = (id) => {
    setTodos(todos.map((todo) =>
      todo.id === id ? { ...todo, isDone: !todo.isDone } : todo
    ));
  };

특정 id를 가진 할 일 항목의 완료 상태를 토글하는 함수

id를 매개변수로 받은 뒤, map()메서드를 사용하여 todos 배열을 순회한다.

map()메서드는 각 항목에 대해 주어진 함수를 실행하고, 그 결과로 새로운 배열을 생성한다.

현재 순회 중인 할 일 항목의 id가 매개변수로 전달된 id와 일치하는지 확인 후, 차이면 해당 할 일의 항목 상태를 변경한다.

스프레드 연산자를 사용하여 현재 할 일 항목의 모든 속성을 복사한 후 , isDone 속성만 토글하여 변경한다.

setTodos 함수를 사용하여 변경된 할 일 목록을 todos 상태로 업데이트한다. 변경된 목록은 기존의 todos 배열을 복사하되, 특정 id에 해당하는 할 일 목록의 완료 상태를 토글하여 업데이트해주도록 한다.


 return (
    <div className="container">
      <h1>할 일 목록</h1>
      <form onSubmit={onSubmitHandler}>
        <input
          type="text"
          placeholder="제목을 입력해주세요"
          value={title}
          onChange={onChangeTitle}
        />
        <input
          type="text"
          placeholder="내용을 입력해주세요"
          value={body}
          onChange={onChangeBody}
        />
        <button type="submit">추가하기</button>
      </form>
      <div>

이전과 비슷하게 틀을 짜놓은 코드.

value={title}를 사용하여 입력 필드의 값과 React 상태 변수 title을 연결해줘서 동기화 시킨다.

onChange={onChangeTitle}을 사용하여 입력 필드의 값이 변경될 때 호출되는 함수를 지정해준다.

사용자가 입력할 때마다 onChangeTitle 함수가 호출되어 입력 값이 업데이트 된다.


 <h2>진행 중</h2>
        <ul>
          {todos.filter(todo => !todo.isDone).map((todo) => (
            <li key={todo.id}>
              <span>{todo.title}</span>
              <span>{todo.body}</span>
              <button onClick={() => onToggleHandler(todo.id)}>
                완료
              </button>
              <button onClick={() => onDeleteHandler(todo.id)}>
                삭제
              </button>
            </li>
          ))}
        </ul>

todos 배열에서 isDone 속성이 false인 항목만 필터링하고, 이를 매핑한다.
filter 메서드를 사용하여 배열의 각 요소를 순회하며 주어진 조건을 만족하는 요소만을 걸러내어 새로운 배열을 반환하고, false인 경우만 반환한다.

map 메서드를 사용하여 배열의 각 요소를 순회하며 각 요소에 주어진 함수를 적용하여 새로운 배열을 반환해준다.
map 메서드를 사용하여 jsx로 변환해주고, 변환하는 과정에서 해당 항목의 정보를 화면에 표시하고, 클릭 이벤트를 처리하는 버튼을 생성해준다.

react에선 반복되는 요소를 생성할 때

  • 위와 같이 고유한 식별자를 지정해주는 jsx 코드를 사용한다.


            <h2>완료됨</h2>
            <ul>
              {todos.filter(todo => todo.isDone).map((todo) => (
                <li key={todo.id} className="done">
                  <span>{todo.title}</span>
                  <span>{todo.body}</span>
                  <button onClick={() => onToggleHandler(todo.id)}>
                    취소
                  </button>
                  <button onClick={() => onDeleteHandler(todo.id)}>
                    삭제
                  </button>
                </li>
              ))}
            </ul>
          </div>
        </div>
      );
    }
    
    export default App;
    

    완료도 위와 같은 원리.

  • profile
    프론트엔드 개발자를 향해서

    0개의 댓글