투두리스트 휴지통 만들기 (데이터 옮기기!)
쓰레기통을 처음 생각할 당시만 해도 위의 사진과 같이 투두리스트 컴포넌트(Home.jsx)의 자식 컴포넌트로 휴지통 컴포넌트(Trash.jsx)를 만드려고 했었습니다.
하지만 페이지 라우팅을 배운 김에 활용해 보기 위해 컴포넌트를 분리시켰습니다. 이렇게 분리를 시키니 데이터 이동에 대한 고민이 생길 수밖에 없었습니다.
물론 최상위 컴포넌트인 App 컴포넌트를 사용하면 간단하게 옮길 수 있습니다! 그러나 페이지의 최종 컴포넌트를 각각 Home.jsx와 Trash.jsx로 나눠놓은 상태에서, 다시 최종 컴포넌트의 최종 컴포넌트를 만드는 꼴이 된다는 생각이 들었어요
그래서 App 컴포넌트를 활용하고 싶지는 않았습니다.
https://studysmart.tistory.com/93
투두리스트 로컬스토리지에 저장하기
기존의 투두리스트는 새로고침을 하면 모든 값이 초기화되어 버렸다. 새로고침을 해도 입력했던 정보들이 유지되는 방법을 찾다가, 로컬스토리지를 활용하는 방법을 찾았다. Local Storage란? 서버
studysmart.tistory.com
그러다 문득 생각난 것이, 어차피 Local Storage에 TodoItem이 저장되도록 설정했으니, 이를 이용해 보자! 였습니다.
순서는 다음과 같습니다.
1. Home.jsx에서 삭제되는 요소들을 State에 따로 저장한다.
2. 키 값을 ’trash’로 설정해서 LocalStorage에 별도로 올린다.
3. Trash.jsx는 Local Storage로부터 데이터를 받아와서 처리한다.
4. Trash.jsx가 처리한 데이터를 다시 Local Storage에 업데이트시킨다
시작하기 전에 Home.jsx에서 Todos를 어떻게 LocalStorage에 업데이트 했었는지 다시 확인했습니다요(복습 복습)
Home.js
마운트시 로컬 스토리지에 키값 “todos”가 있으면 가져오고, 없으면 빈 배열을 가져와서 localTodos 변수에 저장합니다. localTodos 변수는 투두리스트를 저장하는 todos State의 기본 값이 됩니다.
todos State가 업데이트될 때마다, useEffect를 통해 로컬스토리지의 “todos”에 todos State를 업데이트시킵니다.
복습 끝! 시작합니다.
1. Home.jsx에서 삭제되는 요소들을 State에 따로 저장
TodoItem을 삭제시키는 핸들러입니다.
삭제 원리는 삭제버튼이 눌린 객체의 Id와 일치하지 않는 객체만을 반환하는 겁니다. 이렇게 되면 일치하는 객체는 반환되지 않으며 최종적으로 todos State에서 사라지게 되겠죠.
반대로 쓰레기통에서는 이렇게 일치하는 요소가 필요하기에 일치하는 요소만 반환받을 것입니다!
삭제 요소를 저장할 trash State를 선언해 줍니다.
삭제버튼이 눌린 id에 해당하는 객체 값을 Trash로 업데이트합니다.
두 번째 todoItem을 삭제하고 console창을 확인해 보면 삭제된 요소가 잘 들어가는 것을 확인할 수 있습니다. 하지만 이대로 데이터를 받으면, 여러 요소를 한 번에 받을 수 없고, 배열을 계속 받게 되기에 약간 수정하겠습니다.
반환되는 배열의 객체만 계속 저장되게 하였으며, 기존의 trash값을 앞에 넣어줌으로써 여러 요소를 한 번에 받을 수 있게 했습니다.
삭제된 모든 요소들이 trash State에 잘 저장되는 것을 확인할 수 있습니다.
2. 키 값을 ’trash’로 설정해서 LocalStorage에 올린다.
기존의 todos를 localStorage로 올리는 코드에 trash를 추가하게 설정했습니다. trash 값이 변동될 때마다 똑같이 localStorage에 업데이트될 것입니다.
[안녕, 잘가] 두 개의 TodoItem을 만들었습니다. ‘잘가’를 삭제했을 때, ‘잘가’는 trash에, ‘안녕’은 todos에 있는 것을 확인할 수 있습니다.
하지만 이대로 끝내면 투두리스트가 새로고침 될 때마다 trash 값이 초기화될 것입니다. 그렇기에 새로고침을 해도 그대로 값을 남아있게 하기 위해 코드를 추가할 것입니다.
기존의 투두리스트 로직과 동일합니다. 페이지가 마운트 됐을 때, localStorage에 ‘trash’가 있다면 가져오고 없다면, 빈 배열을 반환하는 변수 localTrash를 생성합니다.
그리고 localTrash를 trash State의 기본값으로 주면, 새로고침을 해도 trash값이 초기화되지 않습니다.
!!! 아이디 중복 문제 또 발생...
새로 생성되는 요소의 id는 기존 요소들의 'id의 최댓값 +1'입니다. 즉 TodoItem을 다 지워버리고 새로 생성하면 새로 생성되는 요소의 id는 다시 0부터 시작합니다..
하지만 지운 요소는 trash에 보관되기에 중복이 발생할 수밖에 없습니다.
근데 그냥 'trash의 id도 받아서 최댓값을 같이 카운트하면 되지 않나?'라는 생각이 들었습니다.. 예.. 바로 해결할 수 있을 것 같습니다.
지난번에 만들었던 id 생성 로직입니다. 이 로직에서 todos의 id 뿐만 아니라, trash의 id 또한 함께 받습니다. 그리고 한꺼번에 합친 후, 합친 값의 최댓값+1을 새로운 요소의 id로 사용하면 될 것 같습니다.
todos의 id 뿐만 아니라, trash의 id도 배열로 반환받습니다(countingTrash) 그리고 concat 메서드를 이용해서 두 배열을 합쳐준 뒤 allInOneId 변수에 저장합니다. console.log을 통해 allInOneId 변수를 출력해 보겠습니다.
allInOneId 변수의 배열은 [todo id + trash id] 구조로 되어 있습니다.
- 첫 줄은 todos의 id 0,1,2를 나타냅니다. [0,1,2 + ]
- 두 번째 줄은 todos의 id 1,2 그리고 삭제된 요소의 아이디 0번 [1,2 + 0]
- 세 번째 줄은 todos의 id 2, 그리고 삭제된 요소의 아이디 0번, 1번 [2 + 0,1]
- 네 번째 줄은 todos의 id는 없고 삭제된 요소의 아이디 0,1,2 [ + 0,1,2]
즉 이렇게 todos와 trash의 id를 통합해서 관리하고, 이를 활용해서 새로운 요소의 id를 생성하면 id가 중복될 일이 없어지겠죠
id를 통합한 변수인 allInOneId 변수를 기준으로 로직을 수정해 줍니다.
쓰레기통에 id가 10번까지 있는 상태에서 새로운 todo를 만드니, id가 11로 생성되는 것을 확인할 수 있습니다.
★해결★
Trash.jsx는 Local Storage로부터 데이터를 받아와서 처리한다.
쓰레기통 컴포넌트가 마운트 될 때, 로컬 스토리지로부터 데이터를 받아오게 설정했습니다. console.log를 찍어보면 삭제된 요소들이 잘 반환되는 것을 확인할 수 있습니다.
이제 받아온 값을 화면에 렌더링 하면 됩니다. 과정은 TodoList에서 TodoItem을 생성하는 로직과 동일하기에 생략하겠습니다.
삭제한 요소가 쓰레기통 컴포넌트에 렌더링 되는 과정까지 완성했습니다.
이제 각 버튼을 눌렀을 때 실행될 로직만 구성하면 됩니다!