[React] To Do List

hyeryeon·2024년 2월 25일
post-thumbnail

초기 to do list

import { useState } from "react";

function App() {
  const [toDo, setToDo] = useState("");
  const onChange = (event) => setToDo(event.target.value);
  const onSubmit = (event) => {
    event.preventDefault();
    if (toDo === "") {
      return;
    }
    setToDo("");
  };
  
  return (
    <div>
      <form onSubmit={onSubmit}>
        <input
          onChange={onChange}
          value={toDo}
          type="text"
          placeholder="Write your to do..."
        />
        <button>Add To Do</button>
      </form>
    </div>
  );
}

export default App;

form은 기본적으로 submit 이벤트를 갖고 있다.
그러므로 event.preventDefault() 함수를 이용하여 기본 동작을 막아주었다.

이제 여러 개의 toDo를 받을 수 있는 배열이 필요하다.
따라서 또 하나의 useState를 만들어주고 초기 값에 [] 배열을 넣어준다.
그리고 이 배열에 toDo들을 추가할 예정인데..

const인 useState의 첫 번째 인자 값은 절대 건드리지 않는다.

즉, toDos.push 이런식으로 하지 않는다는 것이다.
우리는 두 번째 인자 값을 가지고 수정을 거쳐야한다.


map()함수

배열에 있는 각 요소를 돌며 지정된 함수가 실행되므로, 배열에 있는 요소의 개수만큼 함수가 실행됩니다. 그리고 각 함수의 반환값이 새로운 배열에 저장됩니다.

예를 들어, ['a', 'b', 'c', 'd', 'e', 'f'].map(() => ":)")와 같은 코드를 사용하면,
-> 새로운 배열 [':)', ':)', ':)', ':)', ':)', ':)']가 생성됩니다.
여기서 각 원소들이 이전 배열의 원소에 적용된 함수의 반환값입니다.

✨map() 함수를 사용하면 기존 배열을 직접 수정하지 않고, 새로운 배열을 반환합니다.
그리고 이 새로운 배열은 기존 배열과 다른 객체입니다.

✨map((item) => item.toUpperCase())와 같은 코드를 사용하면 배열의 각 요소를 대문자로 변환한 새로운 배열이 생성됩니다.

React에서는 보통 리스트의 각 요소를 렌더링할 때 map() 함수를 사용합니다. 그러나 React는 각 요소가 고유하게 식별되어야 하기 때문에, 리스트를 렌더링할 때는 각 요소에 고유한 키(key)를 제공해야 합니다. 이 키는 각 요소를 식별하는 데 사용됩니다.

따라서 map() 함수의 두 번째 매개변수로는 현재 요소의 인덱스를 받아올 수 있습니다. 이를 이용하여 각 요소에 고유한 키를 제공할 수 있습니다. 이렇게 하면 React는 각 요소를 고유하게 식별할 수 있습니다.

... 배열분할 연산자 spread operator

const food = [ 1, 2, 3, 4 ] 가 있다고 치자.

배열 안에 6을 넣고 싶다.

만약 우리가 [6, food] 이런 식으로 한다면 틀렸다.

✨이것은 [6, []] 이러한 형태를 가지기 때문인데 배열 안에 배열이 있는 것과 같은 꼴이다.
내가 원하는 것은 기존 food 배열 안에 6이란 element를 더하고 싶을 뿐이다!!

따라서 우선 배열을 만들고 [ 6, …food ] 이런 식으로 … 을 사용한다면?

당연히 food 의 elements 들을 돌려줄 것이다.


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 === "") {
      return;
    }
    setToDo("");
    setToDos((currentArray) => [toDo, ...currentArray]);
  };
  console.log(toDos);

  return (
    <div>
	  <h1>My To Dos ({toDos.length})</h1>
      <form onSubmit={onSubmit}>
        <input
          onChange={onChange}
          value={toDo}
          type="text"
          placeholder="Write your to do..."
        />
        <button>Add To Do</button>
      </form>
    </div>
  );
}

export default App;

이제 남은 것은 각각의 toDo들을 컴포넌트화 시킬 것이다.

map 함수를 이용해서 말이다.

[’hello’, ‘hi’] 와 같은 배열이 있다고 치자.
map 함수는 안에 있는 element 들을 바꾸고 싶고, 다 바뀐 새로운 배열을 갖고 싶을 때 사용한다.
위 배열에 사용하면 [’hello’, ‘hi’].map() 이다.

이 함수는 array의 모든 item에 대해 실행된다.
무엇을 retrun하던지 간에 그 값이 새로운 배열에 들어가게 될 것이다.

그리고 만약 [’hello’, ‘hi’].map(() => "cat") 이러한 형태라면,
cat을 배열 안에 2번 return 시켜 모든 item을 바꿔버린다.

✨결과 값은 [’cat’, ‘cat’] 이 될 것이다.

물론 위와 같이 사용한다면, 기존에 모든 item들이 cat 으로 바뀌어버릴 것이다.
하지만, map 함수의 첫 번째 인자로 현재의 item을 가져올 수 있다는 것이 의미있다.

이렇게도 사용할 수 있다.
[’hello’, ‘hi’].map((item) => item.toUpperCase())
예전 array를 가져와 그대로 변형하는 것이다.


{toDos.map((item) => (
          <li>{item}</li>
        ))}

바로 이러한 형태로 사용한다면, toDo의 배열을 가져와 그대로 추가시켜줄 것이다.
-> ✨toDos 배열의 각 요소가 순서대로 리스트의 항목으로 표시

만약, 그냥 {toDos} 로 한다면 toDo들이 각각 컴포넌트화가 되지 않아서
toDo들을 입력하는 그대로 옆에 계속 차곡차곡 겹쳐서 한 줄로 출력되는 것처럼 보인다.

🚩최종코드

import { useState } from "react";

function App() {
  const [toDo, setToDo] = useState("");
  const [toDos, setToDos] = useState([]);
  const onChange = (event) => setToDo(event.target.value);
  //입력란에 입력이 발생할때마다 호출되는 함수 onchange를 정의.입력된 값을 toDo상태로
  const onSubmit = (event) => {
    event.preventDefault();
    if (toDo === "") {
      return;
    }
    setToDo("");  // 입력란을 비워서 새로운 todo 추가 할 수 있게
    setToDos((currentArray) => [toDo, ...currentArray]);
    //기존 todo목록에 새로운 todo추가. 이전배열을 복제하고 새로운배열 맨앞 추가
  };
  console.log(toDos);

  return (
    <div>
      <h1>My To Dos ({toDos.length})</h1>
      <form onSubmit={onSubmit}>
        <input
          onChange={onChange}
          value={toDo}
          type="text"
          placeholder="Write your to do..."
        />
        <button>Add To Do</button>
      </form>
      <hr />
      <ul>
        {toDos.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;




참고블로그

0개의 댓글