23/11/01

Laejun Kim·2023년 11월 1일
1

TIL

목록 보기
26/89

React TodoList 만들기

초안

  • toDos 를 state로 만들고 초기값으로 적당한 배열을 설정한다. 배열 안에는 다수의 객체가 들어가며, 각 객체는 id, title, content, isDone 값을 갖는다.
  const [toDos, setToDos] = useState([
    { id: 1, title: "장보기", content: "고기100g, 우유1팩", isDone: true },
    { id: 2, title: "고양이", content: "사료 챙겨주기, 털 빗질", isDone },
    { id: 3, title: "리액트 공부", content: "과제 시도해보기", isDone },
  ]);
  • input 을 두개 만들어서 각각 title 과 content를 입력할 수 있게 한다. [등록하기] 버튼을 만들고 해당 버튼에 onClick 이벤트에 발동하는 함수를 묶어둔다.
  const registerBtnHndlr = function () {
    const newTodo = { id: toDos.length + 1, title, content, isDone };
    setToDos([...toDos, newTodo]);
    console.log(toDos);
  };
  • 삭제 버튼도 만들어서 해당 버튼을 누르면 setTodos를 통해 해당 id를 가진 객체를 없앤 배열을 새로운 toDos로 만든다.

진행중인 toDo와 완료된 toDo를 어떻게 나눌 것인가?

  • 일단 진행중인 toDo가 표시되는 영역과 완료된 toDo가 표시되는 영역 모두에 똑같이 toDos 배열의 모든 객체를 전부 표시하고 isDone 값에 따라서 해당 div의 className을 변경,
    변경된 className을 통해 CSS에서 display:none 이나 display:block을 설정하는 것을 시도해 보기로 한다.

  • 일단 진행중/완료 양쪽 영역 모두에 정상적이게 toDo 들이 표시되게 하는 것을 시도.

const doneCancelBtnHndlr = (id) => {
    setToDos((prevToDos) => {
      return prevToDos.map((item) => {
        if (item.id === id) {
          return { ...item, isDone: !item.isDone }; 
        }
        return item;
      });
    });
  };

위의 코드로 isDone 값을 독립적으로 바꾸는데까지 성공했다. 또한 isDone 이 true인 경우 버튼에 취소라고 표시되고 false인 경우에는 완료라고 표시되게 하는데까지 성공. {item.isDone ? "취소" : "완료"}이 코드로 생각보다 간단하게 구현했다.

  • 이제 isDone 값에 따라서 각 div 의 className만 바뀌게 만들면 된다.

isDone 값에 따라 className을 어떻게 바꿀 것인가?

js 에서는 함수를 만들고 그 함수를 버튼 클릭에 할당후 함수 내에서 classList.addsetAttribute로 버튼 클릭에 따라 class 명을 어렵지 않게 바꿀수 있었다. 리액트에서는 어떻게 해야 할까?

  • 시도1 : 삼항연산자로 isDone 값에 따라서 다른 값을 변수에 할당하고 그 변수를 className으로 전달.
const divClassName = isDone ? "complete" : "not-complete";
  const combinedClassName = `todo-block ${divClassName}`;

combinedClassName을 한번 거쳐서 toDo 블록들 전체의 모양을 제어하는데 쓸 className도 함께 병기되도록 시도해 보았다.

  • 시도 1 결론
    완전히 실패. isDone은 버튼 클릭에 따라 바로바로 바뀌지만 해당 div 의 className 은 처음 만들어질때의 값 그대로다. 심지어 분명 isDone 이 true 라서 "complete"로 표시되어야할 div 조차 "not-complete"로 표시되는 상황 발생

  • 시도 1 피드백
    왜 "complete"로 표시되어야할 div 조차 "not-complete"로 표시되는지에 대한 해답을 알았다. isDone은 state로 설정되어 있는데, 초기값이 true로 되어 있어서 항상 divClassName 이 "complete"로 설정 되는 것이다.

    게다가 생각해보니, isDone이 state인데 setIsDone으로 isDone을 변경하면 isDone이 사용된 모든 toDo객체가 한번에 변경된다는 문제점도 있다는 것을 발견했다. 구글링 해보니 이에 관한 내용이 한가득 있다.

    현재까지 파악한 바로는 모든 state를 전역 state로 선언해야 하는 것은 아니며 const let 을 함수 내에서 선언해서 그 함수 내에서만 쓰는 것과 마찬가지로 state도 특정 컴포넌트 내에서만 사용되는 local state로 만들수 있다고 한다. isDone을 지역상태로 사용하는 방법을 고민해 봐야하는 시점이다.

0개의 댓글