일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- width속성
- html 태그
- html tag i
- Checked 의사 클래스
- background-color 속성
- tag html
- not 의사클래스
- css
- padding 속성
- iframe
- RGB
- 임베디드
- 아두이노
- html
- sub태그
- i 태그
- focus 의사클래스
- 전체 선택자
- RGBA
- height속성
- go live
- 일반 형제 결합자
- id 선택자
- sup태그
- iframe 태그
- Live Server
- reveal in file explorer
- 인접 형제 결합자
- br 태그
- 자식결합자
- Today
- Total
so woon!
[RECOIL] Selector1 본문
학습일 : 2023. 04. 20
selector는 derived state를 나타낸다.
derived state란, state를 입력 받아서
그걸 변형해 반환하는 순수함수를 거쳐 반환된 값을 말한다.
selector를 사용하면 state 자체가 변하는 것은 아니고
output을 변형하는 것이다.
selector가 있으면 데이터에 좀 더 체계화된 방식으로 접근할 수 있다.
한 곳에 데이터를 몰아넣고 컴포넌트 안에서 그것을 수정하는 대신
atom에 데이터를 모아두고
selector로 데이터를 변형할 수 있다.
<atoms.tsx>
우리는 지금 이 toDoState에 모든 todo들을 담고 있다.
카테고리와 상관없이, 모든 todo 들이 전부 같은 state에 저장되고 있다.
DONE, DOING, TODO 든 뭐든 간에 전부 한곳에 모여 섞여있단 뜻이다.
import { atom } from "recoil";
export interface IToDo {
text: string;
id: number;
category: "TODO" | "DOING" | "DONE";
}
export const toDoState = atom<IToDo[]>({
key: "toDo",
default: [],
});
이젠, selector를 이용해서 이 todo들을 분류해보도록 하자.
다만, atom을 카테고리별로 각각 해서 3개로 늘리고 싶진 않다.
모든 todo들을 하나의 atom에 담고
그 atom의 output을 좀 더 잘 써먹을 수 있는 형태로 변형시켜보자.
(selector는 atom의 output을 변형시키는 도구라고 생각하면 된다.)
이는 selector function을 이용하면 되는데
<atoms.tsx>
selector를 만든다.
key가 필요함,
그리고 get function도 필요하다.
get은 options라는 인자를 받으면서 호출되는데,
options는 객체이다. 그리고 그 객체에는 get function이 들어있다.
get: ({get}) => {}
import {atom, selector } from "recoil";
export interface IToDo {
text: string;
id: number;
category: "TODO" | "DOING" | "DONE";
}
export const toDoState = atom<IToDo[]>({
key: "toDo",
default: [],
});
// selector
export const toDoSelector = selector({
key:"toDoSelector",
get: ({get}) => {
return "hello";
}
});
toDoSelector의 value를 잘 얻을 수 있는지 확인 해보도록 하자.
일단 toDoList.tsx로 가서 selectorOutput을 얻어보자
<ToDoList.tsx>
useRecoilValue() 를 이용해서 selector의 value를 구한다.
const selectorOutput = useRecoilValue(toDoSelector);
console.log(selectorOutput);
개발자 도구를 켜보면 hello가 찍혀나옴
이렇게 selectorOutput에 접근할 수 있다.
selector의 요점은 atom을 가져다가 output을 변형할 수 있다는 것이다.
이것이 get function이 있어야 하는 이유다.
get function이 있어야 atom을 받을 수 있다.
이제 모든 to do 들을 받을 것이다.
<atoms.tsx>
toDos를 선언하고 이 toDoState atom을 받도록 해보자
그리고 toDos.length를 리턴한다고 해보자
get function 을 이용하면 selector의 내부로 atom을 가지고 올 수 있다.
const toDos = get(toDoState);
export const toDoSelector = selector({
key: "toDoSelector",
get: ({ get }) => {
const toDos = get(toDoState)
return toDos.length;
},
});
실행시켜보면
todo가 0개라고 나온다.
이렇게 하는 것이 좋은 것이 뭐냐면, toDoSelector가 atom을 보고 있다는 것이다.
따라서 atom이 변하면 selector도 변하게 된다는 것을 뜻한다.
예를 들면
새 to do를 추가시키면 이렇게 console.log() 도 변하게 된다.
우리는 지금 ToDoList.tsx
에서 selector의 output을 console.log() 하고 있다는 걸 기억하자.
그리고 useRecoilValue()를 이용하여
atom의 output도, selector의 output도 얻을 수 있다는 것은 아주 중요하다.
배열을 리턴하고 싶은데, 그 배열은 다른 배열에 담겨져 있다.
[ [ { } , { } ] ] 모양이라 할 수 있다.
어떻게 하면 될까?
filter function을 써볼 수 있겠는데,
filter function은 배열에서 조건에 맞지 않는 원소들을 제거한 배열을 리턴하게 한다.
즉 todo의 카테고리가 TODO와 같으면 남아있게 되는 것이고 아니면 버려지는 것이다.
두번째로는 DOING
마지막 배열은 toDo의 카테고리가 DONE 일 때
<atom.tsx>
filter function을 사용하여
카테고리가 TODO인 것만 만족하는 원소들만 담아서 리턴,
카테고리가 DOING인 것만 만족하는 원소들만 담아서 리턴,
카테고리가 DONE인 것만 만족하는 원소들만 담아서 리턴
export const toDoSelector = selector({
key: "toDoSelector",
get: ({ get }) => {
const toDos = get(toDoState);
return [
toDos.filter((toDo) => toDo.category === "TODO"),
toDos.filter((toDo) => toDo.category === "DOING"),
toDos.filter((toDo) => toDo.category === "DONE"),
];
},
});
실행시켜보면
selector의 output이 세 개의 빈 배열을 담은 한개의 배열이 되었다.
새 todo를 추가해보면
똑같이 3개의 배열을 담은 하나의 배열이지만
세 배열 중 첫번째 배열에 뭔가가 들어가 있다.
그 배열이 TODO를 담는 배열이기 때문이다!
다른 항목도 추가해보겠당
TODO 배열에는 원소가 4개가 되었고,
DOING과 DONE에는 없다.
이제 첫번째 todo를 DOING으로 바꿔보면
카테고리를 바꿔주면
알맞는 배열에 잘 들어가는 모습을 볼 수 있다.
이제 세 개의 각기 다른 배열을 render 해볼 것이다.
<ToDoList.tsx>
toDos를 render하는 대신 배열을 열 것이다
useRecoilValue(toDoSelector)의 return 값은 배열임을 기억해야 한다.
toDoSelector가 배열을 리턴한다는 것은
atoms.tsx 안에 있는 세 배열을 꺼내기 위해서 이 배열을 여는 것이다.
import { useRecoilValue } from "recoil";
import CreateToDo from "./CreateToDo";
import { toDoSelector, toDoState } from "./atoms";
import ToDo from "./ToDo";
function ToDoList() {
// 배열 안의 배열을 선택하려면 이렇게 배열을 열고 순서대로 이름을 지정하면 된다.
const [toDo, doing, done] = useRecoilValue(toDoSelector);
return (
<div>
<h1>Thorn To Do</h1>
<hr />
<CreateToDo />
<h2>TODO</h2>
<ul>
{toDo.map((toDo) => (
<ToDo key={toDo.id} {...toDo} />
))}
</ul>
<hr />
<h2>DOING</h2>
<ul>
{doing.map((toDo) => (
<ToDo key={toDo.id} {...toDo} />
))}
</ul>
<hr />
<h2>DONE</h2>
<ul>
{done.map((toDo) => (
<ToDo key={toDo.id} {...toDo} />
))}
</ul>
<hr />
</div>
);
}
export default ToDoList;
실행결과
이제 기능 구현은 완료되었다.
'Recoil > 개념정리' 카테고리의 다른 글
[RECOIL] Selector - set 사용하기 (0) | 2023.04.25 |
---|---|
[RECOIL] 로컬 스토리지 저장방법 (0) | 2023.04.25 |
[RECOIL] 카테고리별로 todolist 작성하기 + enum으로 카테고리 관리하기 (0) | 2023.04.21 |
[RECOIL] Selector2 (0) | 2023.04.20 |
[RECOIL] Recoil 시작하기 + Recoil을 사용하여 다크모드 구현하기 (0) | 2023.04.15 |