코린이의 리액트 투두리스트 버그 해결하기 - 왜 undefined 일까..?

REASON·2022년 10월 24일
0

끄적끄적

목록 보기
1/2

예전에 패기있게 만든다고 해놓고 리액트 입문한지 얼마 안됐다고 다른거 하다가 이제야 다시 돌아온 리액트 투두리스트..

코드 네이밍 바꾸고 useReducer 사용해서 todo를 추가할 수 있도록 하는 부분을 구현하고 있다.
발생한 버그는 Add 버튼을 눌러서 투두를 추가했을 때 기대하는 결과는 기존 더미 투두 데이터 3개의 배열에 새로운 todo가 추가된 새 배열이 만들어져야하는데, Add 버튼을 누르는 순간 undefined라서 배열 메서드 못쓴다고 에러가 발생한다. (왜 undefined가 된거지?)

문제로 추정되는 코드 구간

const TodoList = ({ todos }) => {
  console.log(todos);
  return (
    <>
      <TodoLists>
        {Array(todos.length)
          .fill()
          .map((todo, i, arr) => {
            console.log(todo, arr);
            return (
              <MyTodoList key={`${i}번째 to do 아이템`}>
                <Title>{todos[i].task}</Title>
                <RecycleIcon src="recycle_bin.svg"></RecycleIcon>
              </MyTodoList>
            );
          })}
      </TodoLists>
    </>
  );
};

콘솔로 디버깅해보니 분명 배열로 들어오다가 어느순간 undefined가 되어버렸다.

멀쩡한 배열이 왜 undefined가 된건지 조금 더 코드를 살펴보기로 했다.
App.js의 showCreateTodo state가 true로 변경되었을 때 Edit 모드인 CreateForm 컴포넌트가 나타난다.

{showCreateTodo ? (
  <CreateForm
  	id={id}
	setShowCreateTodo={setShowCreateTodo}
 	showCreateTodo={showCreateTodo}
 	dispatch={dispatch}
  />) 
 : (<TodoMain todos={state} />)}

원래 showCreateTodo state도 useReducer로 변경시키는 형태로 코드를 수정했었는데 뇌피셜이지만 이 과정에서 useReducer가 비동기로 처리하는 부분에서 문제가 발생했다고 생각했다.

todo를 추가했을 때 showCreateTodo 상태를 변경시키는 부분을 dispatch를 사용해서 전달시켰는데 컴포넌트가 재렌더링되면서 비동기로 인해 state가 빈 값을 가지는 바람에 가져올 수 없는 건지 state를 찾을 수 없다고 화내서 어쩔수 없이 당장은 useState로 따로 빼서 구현하기로 했다.
일단 useState로 변경시키니 이 부분은 해결이 되었는데 문제는 산 넘어 산.

concat을 잘 사용하는 편은 아니지만 이번엔 concat도 한번 써봤다.
기존 state 배열에 새로운 todo를 추가시키도록 했다.

add 버튼으로 추가시키면 이렇게 데이터가 추가되면서 투두리스트에 추가된 투두까지 렌더링되는 것을 기대하고 있는데undefined 라서 concat 메서드를 사용할 수 없다는 에러가 발생하는데 원인을 모르니 계속 엉뚱한 곳을 고치고 있었던 것 같다....

드디어 고쳤다.

어느 부분에서 에러가 나는지 몰라서 한참 들여다본 결과..
Form으로 submit을 날리고 있는데 Add버튼을 누르면서 또 dispatch를 호출하면서 중복으로 호출해서 발생한 문제였던 것 같다.
Submit만 남기고 Add버튼의 onClick 이벤트를 제거해주니 원하던 대로 정상적으로 동작하는 것을 확인할 수 있었다.

아니 지금보니까 + 버튼 눌렀을 때 버튼 css가 제대로 동작을 안하는 것이 보인다.
스타일드 컴포넌트 이름 변경하면서 바꾸지 않은 부분이 있었던 것 같다. 이건 금방 고치니까 괜찮고..

문제의 중복 코드


  const onSubmit = (e) => {
    e.preventDefault();
    dispatch({
      type: CREATE_TODO,
      todo: {
        task: userTaskInput,
        memo: userMemoInput,
      },
    });

    setUserTaskInput('');
    setUserMemoInput('');
  };

/* 삭제한 코드
  const addTodo = () => {
    dispatch({
      type: CREATE_TODO,
      todo: {
        id: 4, //나중에 수정 해야함
        task: userTaskInput,
        memo: userMemoInput,
      },
    });

    // onClose();
  };
 */

onSubmit과 addTodo가 같은 동작을하고 있어서 에러 발생 + 같은 todo가 2번 등록되는 현상이 발생했다. 같은 todo가 2번 찍히는 것은 디버깅 중에 발견했는데 뭐지..?하다가 내가 같은 이벤트를 두개나 건게 문제였다는 것을 알 수 있었다.

결국 처음에 문제로 추정했던 부분의 문제가 아니라 중복 작성한 코드로 인해 발생한 문제였다.

너무 어려운 버그의 세계...ㅠㅠ 오늘도 이거 찾느라 다른거 해야지~했었는데 오기가 생겨서 버그 고친다고 컴포넌트 파일만 하루종일 왔다갔다 하느라 다른건 제대로 하지도 못한 것 같다. ㅋㅋㅋ
그래도 일단 고쳐서 좋아....

어? 그렇다면 아까 useState로 변경한 코드도 다시 useReducer의 기본 상태값으로 넣으면 정상적으로 동작하지 않을까..! 싶어서 일단 삭제 기능 구현 먼저 해보고 useReducer로 넣는 작업을 해볼 생각이다.

0개의 댓글