<JS> class를 추가했는데 DOM이 두 번 렌더링 되는 경우

·2024년 5월 24일
0

JavaScript

목록 보기
5/11
post-thumbnail

문제

짤처럼 취소선이 생기면서 checked class가 붙게되는데, 이 때 ul 전체 요소가 새로 붙혀지는 문제를 발견하였다. 그와 동시에 todo 요소의 순서가 변경되는 문제도 발생했다.

  1. 클릭 이벤트가 생기고, checked class가 li요소에 붙음
  2. 이후에 ul 전체가 새롭게 업데이트되어 todo 요소의 순서가 변경되는 현상 발생

해결

  1. 취소선이 생김에 따라 update 함수가 실행된다.
  2. supabase table이 업데이트됨에 따라 TodoList를 다시 불러와야한다.
  3. TodoList를 불러오는refreshTodoList함수에 update라는 매개변수를 하나 추가했다. 매개변수 update의 기본값은 false이고, update를 담당하는 함수가 실행될 때, 매개변수 updatetrue를 받게된다.
  4. 매개변수 update의 상태를 분기로 삼아 불필요한 DOM 렌더링을 막았다.

➡️ 결과적으로 취소선이 생길 때, ul요소가 업데이트되는 것이 아닌, 내가 클릭한 li요소에 checked class만 추가되게 수정했다.
이로써 DOM이 두 번 렌더링 되는 문제와 함께 todo의 요소가 뒤섞이는 문제가 해결되었다.

  • 문제 코드
// TodoList를 업데이트하는 함수
  async function refreshTodoList() {
    let { data: todoList, error } = await client.from('todoList').select('*')
    const listContainer = document.querySelector('#list_container');
    console.log("todoList : ", todoList)


    const renderTodo = () => {
      // 기존 배열 초기화
      listContainer.innerHTML = "";

      // 배열 업데이트
      todoList.forEach(todo => {
        let li = document.createElement("li");
        li.classList.add('todo');
        li.innerHTML = todo.title;
        listContainer.appendChild(li);

        let span = document.createElement("span");
        span.classList.add('closeBtn');
        span.innerHTML = "\u00d7";

        // 삭제 버튼 이벤트 함수 추가
        console.log("todo : ", todo)
        span.addEventListener("click", () => removeTodo(todo.id));
        li.appendChild(span);
      })
    }

    renderTodo();
  }

  refreshTodoList();
  • 수정 코드
// TodoList를 업데이트하는 함수
  async function refreshTodoList(update = false) {
    let { data: todoList, error } = await client.from('todoList').select('*')
    const listContainer = document.querySelector('#list_container');
    // console.log("todoList : ", todoList)

    if (update === false) {
      const renderTodo = () => {
        // 기존 배열 초기화
        listContainer.innerHTML = "";

        // 배열 업데이트
        todoList.forEach(todo => {
          let li = document.createElement("li");
          if (todo.success) {
            li.classList.add("checked");
          }
          li.classList.add('todo');
          li.id = todo.id;
          li.innerHTML = todo.title;
          listContainer.appendChild(li);

          let span = document.createElement("span");
          span.classList.add('closeBtn');
          span.innerHTML = "\u00d7";

          // 삭제 이벤트 리스너 연결
          span.addEventListener("click", () => removeTodo(todo.id));
          li.appendChild(span);
        })
      }

      // Todo 상태 업데이트 시에 실행
      if (update === true) {
        const updateRenderTodo = () => {
          // 취소선 요소 업데이트
          todoList.forEach(todo => {
            if (todo.success) {
              li.classList.add("checked");
            }
          })
        }
        return updateRenderTodo();
      }
      return renderTodo();
    }
  }

  refreshTodoList();
profile
- 배움에는 끝이 없다.

0개의 댓글