실습/React

[React/JavaScript] 투두 리스트(Todo-List) 만들기 (2)

이우열 2023. 12. 29. 23:26
728x90

 

App.js에 스크립트 파트를 추가하여 동작하도록 만들어 봅시다.

 

 

✅ 새로운 할 일 작성하기

import { useState } from "react";

function App() {
  const [toDo, setToDo] = useState("");
  
  const onChange = (event) => {
    setToDo(event.target.value);
  };

  return (
    <>
      <h1>Todo List</h1>
      <form>
        <input id="todo" type="text" value={toDo} onChange={onChange} />
        <button id="addBtn" type="submit">
          +
        </button>
      </form>
      <ul id="todoBox"></ul>
    </>
  );
}

export default App;

 

useState 훅을 사용하여 input 태그에 입력한 값을 toDo라는 문자열 state로 지정해줍니다.

 

input 태그에는 value 값으로 toDo를 중괄호로 사용해서 지정해주고

만약 input의 값이 변경된다면 onChange 이벤트가 발생하여 onChange 함수가 실행되게 해줍니다.

 

onChange에서는 event가 발생한 타겟의 값을 가져와

setToDo를 통해 그 값을 toDo에 업데이트해줍니다.

 

 

✅ 새로운 할 일 저장하기

import { useState } from "react";

function App() {
  const [toDo, setToDo] = useState("");
  const [toDos, setToDos] = useState([]);

  const onChange = (event) => {
    setToDo(event.target.value);
  };
  const onSubmit = (event) => {
    event.preventDefault();
    if (toDo.trim() !== "") {
      setToDos((currentArray) => [...currentArray, toDo]);
      setToDo("");
    }
  };

  return (
    <>
      <h1>Todo List</h1>
      <form onSubmit={onSubmit}>
        <input id="todo" type="text" value={toDo} onChange={onChange} />
        <button id="addBtn" type="submit">
          +
        </button>
      </form>
      <ul id="todoBox">
        {toDos.map((item, index) => (
          <li key={index}>
            {item}
            <button>remove</button>
          </li>
        ))}
      </ul>
    </>
  );
}

export default App;

 

이제 "+" 버튼을 클릭하면 toDo에 있는 값이 toDos누적되도록 해줍시다.

 

  • toDosuseState를 통해 배열로 선언해줍니다.
  • form 태그에 onSubmit 이벤트에 onSubmit 함수를 연결해주고 submit 버튼인 "+" 버튼을 클릭했을 때 onSubmit 함수가 실행되게 해줍니다.

onSubmit 함수에서는 event를 인자로 받는데 인자로 받은 이유는 기본적인 form 전송 이벤트를 막기 위함입니다.

 

HTML 코드에서 form이 전송되면 페이지가 새로고침되는데 이는 리액트와 같은 SPA(Single Page Application)을 사용하는 이유와 연결됩니다.

SPA에서는 새로고침 없이 화면을 재렌더링하기 위해서 사용하기 때문에 기존에 form이 전송되면 새로고침하는 이벤트를 막아줘야 합니다.

event.preventDefault() 코드로 새로고침되는 것을 막아줍시다.

 

  • toDoinput 값이 공백이 아니라면 setToDos를 사용해 toDos를 업데이트해줍니다.

state를 업데이트하는 함수(setToDos)에서는 이전 상태 (prevState)를 파라미터로 전달합니다. 

이 함수는 새로운 상태를 반환하고, React는 반환된 값을 적용합니다.

함수 형태를 사용하는 이유는 비동기적 업데이트 시에 이전 상태를 안전하게 참조하기 위함입니다. 

특히, 여러번의 연속된 상태 업데이트에서 이전 상태를 정확하게 참조하려면 함수형 업데이트를 사용해야 합니다.

 

setToDos에서 함수형으로 사용해 이전 상태의 값을 복사하고 toDo를 추가해 새로운 배열을 생성해 toDos를 업데이트해줍니다.

 

  • toDo공백으로 초기화해줍니다.
  • ul 태그 안에 toDos를 하나하나 li 태그로 만들어줍니다.

map 메소드롤 통해 각 요소에 접근하고 요소의 (item, index)를 가져옵니다.

이 때, item은 배열의 값이고 index는 배열의 인덱스가 됩니다.

 

가져온 값을 통해 li 태그를 만들고 keyindexvalueitem으로 지정해줍니다.

제거할 수 있는 버튼도 추가해줍시다.

 

 

✅ 할 일 제거하기

import { useState } from "react";

function App() {
  const [toDo, setToDo] = useState("");
  const [toDos, setToDos] = useState([]);

  const onChange = (event) => {
    setToDo(event.target.value);
  };
  const onSubmit = (event) => {
    event.preventDefault();
    if (toDo.trim() !== "") {
      setToDos((currentArray) => [...currentArray, toDo]);
      setToDo("");
    }
  };
  const onRemove = (index) => {
    setToDos((currentArray) => currentArray.filter((_, i) => i !== index));
  };

  return (
    <>
      <h1>Todo List</h1>
      <form onSubmit={onSubmit}>
        <input id="todo" type="text" value={toDo} onChange={onChange} />
        <button id="addBtn" type="submit">
          +
        </button>
      </form>
      <ul id="todoBox">
        {toDos.map((item, index) => (
          <li key={index}>
            {item}
            <button onClick={() => onRemove(index)}>remove</button>
          </li>
        ))}
      </ul>
    </>
  );
}

export default App;

마지막으로 remove 버튼을 클릭했을 때 리스트에서 선택한 할 일이 지워지도록 해봅시다.

 

onRemove 함수를 만드는데 이 함수에는 index가 필요합니다.

배열에서 선택된 index를 제외한 값들만을 남겨야 하기 때문입니다.

 

현재 배열에서 filter 메소드를 사용하여 i인 탐색 인덱스가 선택된 index와 같지 않은 경우만 남겨줍니다.

이렇게하면 선택한 index의 값은 걸러지고 남은 값들만 toDos에 남게 됩니다.

 

button 태그에서 onClick 이벤트에 onRemove 함수를 연결하여 map에서 받아온 index를 인자로 넘겨주면 끝이 납니다.

 

 

✅ 결과

todo 리스트 동작 결과

 

728x90