일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- RGB
- not 의사클래스
- i 태그
- 일반 형제 결합자
- iframe 태그
- 인접 형제 결합자
- padding 속성
- sup태그
- background-color 속성
- width속성
- reveal in file explorer
- 전체 선택자
- br 태그
- html
- css
- focus 의사클래스
- Checked 의사 클래스
- id 선택자
- tag html
- 자식결합자
- sub태그
- 임베디드
- html tag i
- Live Server
- height속성
- iframe
- go live
- html 태그
- 아두이노
- RGBA
- Today
- Total
so woon!
[REACT] 클릭시 카테고리 바꾸기1 본문
학습일 : 2023. 04. 19
이번 글에서는
사용자들이 버튼을 이용해서
toDo의 카테고리를 바꿀 수 있는 기능을 추가해보고자 한다.
그리고 toDo의 카테고리에 따라서 알맞는 버튼만 보이게 할 것이다.
카테고리를 받아오고, 카테고리가 "DOING" 이 아닐 때만
DOING 버튼을 보여주도록 조치한다.
import { IToDo } from "./atoms";
function ToDo({ text, category }: IToDo) {
return (
<li>
<span>{text}</span>
<button>TODO</button>
{category !== "DOING" && <button>Doing</button>}
<button>Done</button>
</li>
);
}
export default ToDo;
아래에도 똑같이 해주겠당.
import { IToDo } from "./atoms";
function ToDo({ text, category }: IToDo) {
return (
<li>
<span>{text}</span>
{category !== "TODO" && <button>TODO</button>}
{category !== "DOING" && <button>DOING</button>}
{category !== "DONE" && <button>DONE</button>}
</li>
);
}
export default ToDo;
실행시켜보면
등록한 리스트는 TODO 카테고리에 있기 때문에
TODO 버튼은 안뜨고
DOING, DONE 버튼만 뜨게 된다.
이번에는 toDo의 카테고리를 바꾸는 함수를 만들 차례이다.
함수 하나로 해결할 수 있는데
이름을 onClick으로 지어주겠다.
이 함수를 호출할 때, 특정한 카테고리를 인자로 받고 싶다.
예를 들자면, 어떤 사용자가 DOING 버튼을 클릭하게되면,
인자를 통해서 DOING 버튼이 클릭이 되었다는 것을 알고 싶다는 의미이다.
이름을 newCategory로 설정하고 이 함수를 세 버튼의 onClick 함수로 설정하고자 한다.
각각 TODO, DOING, DONE 을 적어주어 인자가 있는 onClick event 처리를 해준다.
그냥 onClick={onClick} 이라고 해주면 인자가 넘어가지 않음
<ToDo.tsx>
import { IToDo } from "./atoms";
function ToDo({ text, category }: IToDo) {
// newCategory가 IToDo의 category 항목이라는 것을 알려줌
const onClick = (newCategory: IToDo["category"]) => {
console.log("i wanna to ", newCategory); // 콘솔에 찍어보면
};
return (
<li>
<span>{text}</span>
{category !== "TODO" && (
<button onClick={() => onClick("TODO")}>TODO</button>
)}
{category !== "DOING" && (
<button onClick={() => onClick("DOING")}>DOING</button>
)}
{category !== "DONE" && (
<button onClick={() => onClick("DONE")}>DONE</button>
)}
</li>
);
}
export default ToDo;
실행결과
조금 다른 방법으로 해보면,
newCategory가 IToDo의 category 항목이라는 것을 알려줌
const {currentTarget:{name}} = event; 를 적어주어
currentTarget으로 이벤트를 발생시킨 버튼의 name을 잡아주면 된다.
다음으로는 toDo를 수정하는 부분을 해볼텐데
id가 있기 때문에 어떤 toDo를 수정해야 하는지 이미 알고 있기 때문에 편하다.
function ToDo({ text, category, id }: IToDo)
id를 적어 추가해준다
이젠 atom을 수정 가능하게 해주어야 할 것이다.
전에 했던 방식처럼 useSetRecoilState을 사용하면 된다.
따라서 setToDos라는 이름으로 만들어주겠다
<ToDo.tsx>
import { useSetRecoilState } from "recoil";
import { IToDo, toDoState } from "./atoms";
function ToDo({ text, category, id }: IToDo) {
const setToDos = useSetRecoilState(toDoState);
const onClick = (event:React.MouseEvent<HTMLButtonElement>) => {
const {currentTarget:{name}} = event;
};
return (
<li>
<span>{text}</span>
{category !== "TODO" && (
<button name="TODO" onClick={onClick}>TODO</button>
)}
{category !== "DOING" && (
<button name="DOING" onClick={onClick}>DOING</button>
)}
{category !== "DONE" && (
<button name="DONE" onClick={onClick}>DONE</button>
)}
</li>
);
}
export default ToDo;
다음으로 살펴볼 것이 있는데,
<ToDoList.tsx>
toDos를 console.log 해보면
console.log(toDos);
이런 결과가 나오는데
index 2번 TODO의 카테고리를 변경시켜보도록 하자!
카테고리를 바꾸기 위해서
state를 mutate하면 안되며, 우리는 새로운 state를 만들어야 한다.
일단 개발자도구에 뜬 마지막 object를 우클릭 후 카피 해준 다음
ToDo.tsx에 붙여넣어서 잘 살펴보면
1. 우리는 id로 TODO를 찾아야 함을 알게 될 것이다.
2. 두번째로는 TODO의 index를 알면 된다.
3. 결국 우리는 이 array 안에 있는 object의 index를 찾는 방법만 알면 되는 것이다.
확인했으니 잘 지워주고
수정하고자 하는 to do의 경로를 찾아보자
그러기 위해 먼저 setToDos를 해줄 것이다.
setToDos를 사용하면 값을 즉시 변경할 수 있고,
현재 값 또는 oldToDos를 argument로 주는 함수를 만들 수 있다.
타겟의 현재 경로를 받아야 하므로
oldToDos를 받아서 그냥 다시 리턴하는 함수를 만들어준다
(이 경우엔 같은 state를 유지하기 때문에 re-render가 일어나지 않는다.)
findIndex 안에서는 조건을 만족하는 to do의 index를 찾아 줄 것이다.
toDo의 id와 props에서 오는 id가 같은지 비교해주면 된다.
<ToDo.tsx>
import { useSetRecoilState } from "recoil";
import { IToDo, toDoState } from "./atoms";
function ToDo({ text, category, id }: IToDo) {
const setToDos = useSetRecoilState(toDoState);
const onClick = (event: React.MouseEvent<HTMLButtonElement>) => {
const {
currentTarget: { name },
} = event;
// setToDos
setToDos((oldToDos) => {
// toDo의 id와 props에서 오는 id가 같은지 비교
// 여기서 oldToDos의 array를 받아오고 있고 이 array에서 toDo의 index를 찾기 위해
// toDo의 id가 props에서 온 id와 같은지 비교하고 있다.
const targetIndex = oldToDos.findIndex(toDo => toDo.id === id)
return oldToDos;
});
};
return (
<li>
<span>{text}</span>
{category !== "TODO" && (
<button name="TODO" onClick={onClick}>
TODO
</button>
)}
{category !== "DOING" && (
<button name="DOING" onClick={onClick}>
DOING
</button>
)}
{category !== "DONE" && (
<button name="DONE" onClick={onClick}>
DONE
</button>
)}
</li>
);
}
export default ToDo;
실행결과
이렇게 우리는 이제 taget의 경로를 찾게 되었다.
첫번째 단계는 끝났다.
다음으로 해야할 것은
우리는 기본적으로 to do를 만들어서
원래의 to do를 업데이트 해야한다.
따라서 우리는 새 카테고리로 새로운 to do를 만들어야 한다.
oldToDo를 만들고
const oldToDo = oldToDos[targetIndex];
newToDo도 만들어 보자
newToDo는 object가 될 것이고 기존의 to do와 똑같은 props를 가지게 될 것이다.
text:text 이렇게 써주지 않아도 된다.
위에서 받은 text, id 를 써주고, category는 조금 다르게 써주어야 하는데
위 props에서 온 category 가 아니라 클릭된 버튼의 카테고리를 가져야 하기 때문에
category: name 이라 써주면 된다.
const newToDo = {text, id, category: name};
oldToDo와 newToDo를 console에 찍어보면
뒤에나오는 newToDo는 내가 클릭해준 버튼의 상태대로 정상적으로 바뀜을 볼 수 있다.
'ReactJS > 개념정리' 카테고리의 다른 글
[REACT] Drag and Drop1 (0) | 2023.04.25 |
---|---|
[REACT] 클릭시 카테고리 바꾸기2 (1) | 2023.04.20 |
[REACT] Refactoring (0) | 2023.04.19 |
[REACT] todolist 만들기 (0) | 2023.04.18 |
[REACT] useRecoilState 사용하기 (0) | 2023.04.18 |