
#6.11 ~ 6.14 2023.04.24 (월)
이번 강의부터는 recoil을 중점으로 해보자. toDo를 제출하면 ul로 렌더링되게 해보자.
ToDoList.tsx파일을 src/component 폴더안에 옮겨주고, 당장은 ToDoList 컴포넌트에 모든 걸 넣지만 나중에 다분리시겨줄 거임.

interface IToDo {
text: string;
id: number;
category: "TO_DO" | "DOING" | "DONE";
}
const toDoState = atom<IToDo[]>({
key: "toDo",
default: [],
});
폼이 제출되고 데이터가 모두 유효하다면 state를 바꾸는것을 해보자!
setToDos([])
setTodos(() => {})
toDos.push() // X

setToDos()에 이전의 state를 oldToDos로 받으면 oldToDos는 배열이기 때문에 구조분해할당으로 []를 벗겨줌.data: IForm은 {toDo}: IForm로 바꿈.{ text: toDo, id: Date.now(), category: "TO_DO" }로 interface 정한 값이랑 똑같이 들어오게 해줌.이제 할 일을 완료할 수 있는 기능을 추가하기위해 "TO_DO"를 클릭하면 "DOING"이나 "DONE"으로 또는 반대로도 바뀔 수 있게 만들거임.
시작하기전 ToDoList.tsx에 있던 코드들을 분리시키는 리팩토링을 해보자.

CreateToDo.tsx 와 ToDo.tsx 파일을 만들어주고 form을 CreateToDo.tsx로 옮겨줌 (li는 나중에 옮겨줄거임.)

useForm<IForm>(); 으로 고쳐주자.
ToDoList.tsx에서 안쓰는 코드를 지워줌.
컴포넌트들간에 prop을 내려주지 않아도 toDo가 화면에 잘 렌더링됨.
-> 이제 모든 컴포넌트들이 서로를 의존하지 않고, atom으로만 연결됨!

ToDoList.tsx의 li를 ToDo.tsx로 옮겨주자.

ToDo.tsx의 li는 text만 필요하니 prop으로 받아오고 IToDo 인터페이스로 타입을 설정해줌.
ToDoList.tsx는 map함수안에서 ToDo컴포넌트를 렌더링 되게 함
-> 여기서 ToDo의 에러는 ToDo컴포넌트에 text,id,category prop이 필요하다고 타입스크립트가 내고 있음.


첫번째와 같이 prop을 내려주는 방법도 있지만 <ToDo {...toDo} />로도 간단하게 내릴 수 있음.
-> 이렇게 써도 작동하는 이유는, toDos 배열의 toDo원소 하나하나가 ToDo 컴포넌트에 필요한 props와 같은 모양이기 때문!

사용자들이 버튼을 이용해서 toDo의 카테고리를 바꿀 수 있게 하는 기능과 toDo의 카테고리에 따라서 알맞은 버튼만 보이게 해보자.

위와 같이 카테고리가 "TO_DO"이 아닐 때만, To Do버튼이 보이게 만듦.
-> 현재 카테고리(To Do)가 아닌 다른 카테고리 2개(Doing,Done)가 보이게 됨.
이제 toDo의 카테고리를 바꾸는 함수를 만들어 보자.
사용자가 Doing 버튼을 클릭하면, 인자를 통해서 Doing 버튼이 클릭됐다는걸 알아야 함! (그래야 toDo의 카테고리를 "DOING"으로 바꿀 수 있음)

() => )를 선언 해서 onClick 함수를 호출하게 만듦.<button onCkick={onClick}/> : 이렇게 해도 작동은 하지만, 인자는 넘겨지지 않음
위에서 했던 새 익명함수를 선언하는 방법말고 다른 방법도 있음


이제 수정하고 싶은 toDo의 id를 알고, 어느 카테고리로 가야하는지도 알 수 있게 세팅이 완료됨!
이제 특정 to do의 카테고리를 바꿔보자.

console.log(toDos)를 했을때 위와 같이 input창에 입력한 값을 text로 가지는 배열임을 알 수 있음.그럼 수정하고자 하는 to do의 경로를 찾아보자!
첫번째 단계는 id로 to do를 찾아야 함. 3을 가진 to do의 index를 알고 있으니 array 안에 있는 object의 index를 찾는 방법만 알면 됨.

.findIndex() 메소드를 사용해서 조건을 만족하는 to do의 index를 찾아주자.console.log(targetIndex)로 3을 가진 todo의 index를 잘 가져오는 것을 확인함. 두번째 단계는 새로운 to do를 만들어서 새 category로 새로운 to do를 만들어야함.

{text:text, id:id, category: name}이랑 같은 뜻임.
세번째 단계는 위의 oldToDos 배열에서 text:3을 가진 to do원소를 newToDo로 바꿔줄거임.
불변성을 추구하고 mutate를 하고싶지 않다면 새로운 array를 만들면 됨.
#6.15 ~ 6.18 2023.04.25 (화)
이번 강의에서는 배열의 원소를 어떻게 교체하는지에 관한 이론을 배워보자.
원소를 교체하는 이유는 원소의 위치가 바뀌지 않길 바라기 때문임. 하나를 지우고 맨 뒤에 새로운 걸 붙이는 방식은 좋지 않음.
⭐️ 배열의 원소를 교체하는 한가지 예시

[...front, "새로운 원소", ...back])이제 위의 예시를 그대로 todo리스트에 대입해보자.

위와 같이 return 해주면 선택한 원소가 newToDo로 교체된걸 확인 할 수 있음.

"TO_DO" | "DOING" | "DONE" 중에 하나여야 하는데, 그냥 string이라 나는 에러임.as any라고 적으면 타입스크립트에게 체크하지 말라고 할 수 있음.결과화면 ↓

recoil의 selector라는 개념에 대해 배워보자.
Selector 공식문서

useRecoilValue()을 이용해서 selector의 value를 구할 수 있음.
지금 todo state에는 카테고리와 상관없이, 모든 todo들이 저장되고 있는 상황임. 하지만 카테고리에 맞춰 3개의 state를 만드는건 비효율적임.
그래서 이번 강의에서 할 것은, selector를 이용해서 이 todo들을 카테고리에 따라서 분류를 해보자!

[["TO_DO"에 속한 todo], ["DOING"에 속한 todo], ["DONE"에 속한 todo]]이제 각각의 카테고리에 있는 toDo를 한 화면에 렌더링 되게 코드를 바꿔주자.

결과화면 ↓

이번 강의에서는 3개의 카테고리를 한번에 렌더링하지 않고, 한번에 1개의 카테고리만 보여지게 만들어 볼거임.
그러면 사용자가 현재 선택한 카테고리를 저장할 새로운 state를 만들어 보자.

ToDoList.tsx에 원래 있었던 코드를 지워주고 select 태그를 만들어줌.onInput 이벤트 함수를 만들어줌.이제 셀렉트에서 선택된 옵션의 value를 가져올 수 있는것을 확인했고, 이 value를 category state atom과 연결시켜 보자!

useRecoilState()로 atom의 value값과 수정함수를 만들어 줌.option에 To do, Doing, Done 순으로 하셔서 필요성을 못느끼셨겠지만 Doing, Done, To do 순으로 하셔도
select value = "TO_DO"로 되있기 때문에 처음 선택되어 있는 값은 To do 입니다. 시작값, 말그대로 default value라고 생각하시면 됩니다 !
그래서 select에 value를 넣어주지 않고 option의 순서를 바꾸게 되면 처음 페이지에 들어왔을 때 category !== option의 value 일 수 있습니다.
select의 value를 없애시고 option의 순서를 바꿔보시면서 category를 console로 찍어보시면 이유를 아실 수 있을 거에요.)
이제 연결이 완료됨!
다음은 category가 "TO_DO"면 toDo만 render되고, "DOING"이면 doing만, "DONE"이면 "done"만 렌더링되게 해보자.


atoms.tsx파일에서 selector의 get함수로 category state를 가져옴.
결과화면↓


CreateToDo 컴포넌트에서 새 toDo를 추가 할때마다, "TO_DO" 카테고리로만 들어가고 있음.
-> 이번 강의에서는 categoryState에 따라서, 새 toDo의 카테고리가 정해지도록 고쳐보자!

useRecoilValue()로 현재 카테고리를 얻어오고 setToDos 수정함수에 category: category로 변수를 넣어줌 category: category === category 동일함
에러가 생기는 이유는 category는 그냥 string인데, toDo의 category는 세 종류로 제한되기 때문임.

atoms.tsx파일로 가서 위와 같이 타입스크립트에게 categoryState가 세 개 중의 하나일 거라고 알려주면 해결됨!
기본적으로 재사용이 가능한 type이란 걸 만들어서 반복되는 코드를 고침.


이 문제를 해결하려면,as any만 적어주면 됨! 별로 좋은 방법은 아니지만 일단 이렇게 두고 나중에 고쳐볼거임.

이번엔 카테고리 type 방식을 고쳐 볼거임.

"TO_DO"또 쓰고 있는데 이런식으로 통일되지 않은건 좋은 방법이 아님. type은 복붙을 안 하게 해주는 단순한 문법일뿐."TO_DO" | "DOING" | "DONE";을 실수를 방지하기 위해 코드 전체에서 각각 한개씩 사용할 수 있게 고치는 것임.enum은 enumerable 이라는 뜻으로 이제 모든 category의 타입에는 이것을 쓸 거임.

Categories.TO_DO로 바꿔주면됨.

ToDoList.tsx로 가서 value에 적혀있던 string도 고쳐주자.

ToDo.tsx에도 오류가 생김

atoms.tsx에 가서 Categories를 살펴보면, Categories["TO_DO"]의 값은 사실 0이고 나머지 는 각각 1,2로 숫자임.{Categories.DOING + ""}
이제 enum을 원한다면 string으로 인식되게 바꿔볼거임.

💡 enum type을 정하는 방식은 개발자가 데이터가 어떤 모습이기를 원하는지에 달렸음. 예를 들어 database에서는 숫자형식이 더 도움이 될 수도 있으니 원하는 대로 사용하면 됨!