7.6 Deleting To Dos part One

정진우·2023년 11월 1일
0
post-thumbnail

작성한 To Do를 삭제하고 화면을 새로고침하면 localStorage에 저장된 내용이 그대로 화면에 다시 출력되는 문제가 있었는데 화면에서는 삭제를 했지만 localStorage에서는 아직 지우지 않았기 때문에 이러한 문제가 발생했습니다.

localStoragetoDos 배열의 내용을 복사하여 저장하는 곳입니다. 따라서, toDoslocalStorage가 같지 않다는 것을 알고있어야 합니다.

toDos 배열은 웹 브라우저의 localStorage를 이용하여 데이터를 관리하는 것과 유사한 개념이지만, 엄밀한 의미에서는 일반적인 데이터베이스와는 차이가 있습니다. 일반적인 데이터베이스는 SQL과 같은 데이터베이스 관리 시스템을 사용하여 데이터를 저장하고 관리하지만, localStorage는 웹 브라우저에서 지원하는 로컬 저장소이며, 웹 브라우저 내에서 제한된 기능으로 데이터를 저장하고 관리합니다.

[데이터베이스 이해하기] Database(DB), DBMS, SQL의 개념


toDos 배열에서 ToDo를 삭제하면, 화면에서는 ToDo가 삭제된 것처럼 보이지만 localStorage에는 여전히 삭제되지 않은 ToDo가 저장되어 있습니다. 이를 해결하기 위해, localStorage에서도 ToDo를 삭제하도록 코드를 수정할 필요가 있습니다.

만약 toDos 배열에 a가 2개 있다면, 첫 번째 a를 삭제해도 어떤 것이 삭제된 것인지 알 수 없습니다. deleteToDo 함수는 화면에서 어떤 HTML 요소를 삭제해야 하는지는 알고 있지만, 데이터베이스에서 어떤 ToDo 텍스트를 삭제해야 하는지는 알 수 없습니다. 따라서, 각 배열의 아이템에 ID를 부여해서 고유성을 갖게 합니다. ID 값은 랜덤한 숫자를 부여하기 위해 Date.now() 메소드를 사용합니다.


📌 Date.now()

Date.now()는 현재 시간을 밀리초(1000분의 1초) 단위로 반환하는 메소드입니다. 반환된 값은 1970년 1월 1일 0시부터 현재까지 경과된 밀리초를 환산하여 숫자로 표시됩니다.


handleToDoSubmit 함수 내부에는 사용자가 입력한 새로운 ToDo를 toDos 배열에 추가하기 위한 toDos.push(newTodo) 코드가 있습니다. 하지만 이제는 텍스트 대신 새로운 객체를 추가해야 합니다. 함수 내부에 다음과 같이 코드를 추가합니다.

const newTodoObj = {
  text: newTodo,
  id: Date.now(),
};
toDos.push(newTodoObj);

코드에 추가한 후, 기존 텍스트만 보내던 toDos.push(newToDo)toDos.push(newToDoObj)로 수정해야 합니다. 이제 toDos에는 텍스트가 아닌 객체가 저장됩니다.

function handleToDoSubmit(event) {
  event.preventDefault();
  const newTodo = toDoInput.value;
  toDoInput.value = "";
  const newTodoObj = {
    text: newTodo,
    id: Date.now(),
  };
  toDos.push(newTodoObj);
	paintToDo(newTodoObj); // 수정후
  saveToDos();
}

handleToDoSubmit 함수 내부에서 paintToDo 함수를 호출할 때, newToDo라는 텍스트 매개변수를 받습니다. paintToDo 함수에 string으로 newToDo를 전달하는 대신에 객체newTodoObj을 전달합니다.

하지만 이렇게 작성하면 또 다른 문제가 생깁니다. 작성한 내용이 화면에 [object Object]로 표시됩니다. 따라서 paintToDo 함수를 수정해야 합니다.

function paintToDo(newToDo) {
  const li = document.createElement("li");
  const span = document.createElement("span");
  span.innerText = newToDo.text;
  const button = document.createElement("button");
  button.innerText = "❌";
  button.addEventListener("click", deleteToDo);
  toDoList.appendChild(li);
  li.appendChild(span);
  li.appendChild(button);
}

paintToDo 함수는 이제 객체를 매개변수로 받습니다. 객체 newTodoObjtextid라는 프로퍼티를 가지고 있습니다. ToDo가 화면에 제대로 표시되게 하려면 span.innerText = newToDo 부분을 span.innerText = newToDo.text로 수정해야 합니다. 이전에는 newToDo의 매개변수가 문자열이었지만 이제는 객체이므로 객체 newTodoObj의 프로퍼티 text 값을 가져와 span.innerText에 대입해주어야 합니다.

코드를 수정하고 확인해보면 작성한 내용이 화면에 오류 없이 표시되는 것을 확인할 수 있습니다. 이제 각각의 To-Do를 id로 구별하기 위해 paintToDo 함수 내부에 코드를 추가해 줍니다. span.innerText 부분을 보면 객체 newTodoObj의 프로퍼티 text값을 가져와 span.innerText에 대입해서 사용했던 것처럼, 마찬가지로 newTodoObj 객체의 프로퍼티 id를 사용하여 코드를 추가해보겠습니다.

function paintToDo(newTodo) {
  const li = document.createElement("li");
  li.id = newTodo.id; // 추가된 코드
  const span = document.createElement("span");
  span.innerText = newTodo.text;
  const button = document.createElement("button");
  button.innerText = "❌";
  button.addEventListener("click", deleteToDo);
  toDoList.appendChild(li);
  li.appendChild(span);
  li.appendChild(button);
}

li.id = newTodo.id 코드는 paintToDo 함수에서 생성한 To-Do 리스트의 li 요소에 id를 추가하는 코드입니다. 이 idnewTodoObj 객체의 id 값으로 설정되며, To-Do를 생성한 후 li 부분에 id가 업데이트된 것을 확인할 수 있습니다.
li 속성을 추가하는 이유는 삭제 기능을 구현할 때 삭제할 To-Do 의 id를 알아야 하기 때문입니다.

const toDoForm = document.getElementById("todo-form");
const toDoInput = document.querySelector("#todo-form input");
const toDoList = document.getElementById("todo-list");

/** localStorage key값의 이름 */
let TODOS_KEY = "todos";

// newToDo를 submit 할 때마다 newToDo를 toDos라는 빈 배열에 계속 push 한다.
let toDos = [];

/** toDos의 내용을 localStorage에 JSON 문자열 형태로 저장 */
function saveToDos() {
  localStorage.setItem(TODOS_KEY, JSON.stringify(toDos));
  // 로컬 스토리지에 toDos 배열을 JSON 문자열 형태로 저장한다.
  // JSON.stringify() 메소드를 사용하면 객체나 배열을 문자열로 변환할 수 있습니다.
}

/** todo list가 제거되는 함수 */
function deleteToDo(event) {
  const li = event.target.parentNode;
  console.log(li.id);
  li.remove();
}

/** 화면에 todo list가 출력되는 함수 */
function paintToDo(newTodo) {
  const li = document.createElement("li");
  li.id = newTodo.id;
  const span = document.createElement("span");
  span.innerText = newTodo.text;
  const button = document.createElement("button");
  button.innerText = "❌";
  button.addEventListener("click", deleteToDo);
  toDoList.appendChild(li);
  li.appendChild(span);
  li.appendChild(button);
}

function handleToDoSubmit(event) {
  event.preventDefault();
  const newTodo = toDoInput.value;
  toDoInput.value = "";
  const newTodoObj = {
    text: newTodo,
    id: Date.now(),
  };
  toDos.push(newTodoObj);
  paintToDo(newTodoObj);
  // newTodoObj의 입력값을 paintToDo() 함수에 넣어 화면에 출력
  saveToDos();
  // toDos의 내용을 localStorage에 저장
}

toDoForm.addEventListener("submit", handleToDoSubmit);

/** localStorage에 저장된 key를 불러오는 변수 */
const savedToDos = localStorage.getItem(TODOS_KEY);

if (savedToDos !== null) {
  // localStorage에 저장된 savedToDos 변수가 null이 아닌지 확인하는 조건문
  // 저장된 To-Do 리스트가 있는지 확인하고, 있다면 해당 리스트를 화면에 출력하는 역할
  const parsedToDos = JSON.parse(savedToDos);
  // JSON 문자열 데이터를 JSON.parse() 메서드를 사용 JavaScript 객체로 변환
  toDos = parsedToDos;
  // 기존에 저장된 To-Do리스트를 배열에 복원시켜 업데이트
  parsedToDos.forEach(paintToDo);
  // parsedToDos 배열의 각각의 요소에 대해 paintToDo 함수를 실행 화면에 출력
}
profile
내가 바뀌지 않으면 아무것도 바뀌지 않는다 🔥🔥🔥

0개의 댓글