현재 진행중인 프로젝트에서 채팅방 목록을 보여주고,
거기서 삭제하고 싶은 채팅방을 선택, 삭제할 수 있는 기능을 구현중이다.
그런데 내가 사용 중인 MUI에서 ToggleButton 컴포넌트를 사용하니
하나만 체크해도 전체가 체크되는 현상이 발생해서 머리가 아팠다.
체크박스를 누를 때 마다 해당 채팅방의 id를 추출하는 로직은 구현했는데
아무리 머리를 쥐어짜내도 전체가 체크되는 현상을 해결할 수가 없었다.
그러다가 어이없게도 Togglebutton 대신 Checkbox를 사용하니
개별 선택이 가능해졌다.
설마 채팅방 리스트를 보여주는 UI를 구현할 때
채팅방 데이터들이 담긴 리스트를 map함수로 반복해서 생긴 문제인가?
싶어서 각각의 채팅방 id를 뽑아내서 체크박스를 체크할 때마다
조회, 대조해서 해당 체크박스만 활성화시키는 로직도 구현해봤는데
실패해서 완전 망연자실했는데
Checkbox 컴포넌트에서는 아주 상식적인 체크박스 UI가 구현되길래
Togglebutton 컴포넌트는 원래 전체 다 체크되는 컴포넌트였던걸로 결론내렸다.
암튼 구현해낸 UI는 아래와 같다.
axios를 이용해 서버에서 채팅방 데이터를 불러오고
불러온 데이터를 보여주는 UI를
map 함수를 이용해 반복적으로 생성해주었다.
이제 체크된 채팅방만 서버에 DELETE 요청 하고 싶은데
서버 측에서는 채팅방의 ID를 프론트로부터 전달받고
해당 ID를 가진 채팅방을 삭제해주도록 구현해두었다.
아래는 NestJS 서버의 채팅방 삭제 코드인데
아직 DB연결은 안해뒀기 때문에 삭제 요청 시
텍스트 데이터를 반환하도록 설정해두었다.
리액트에서는 아래와 같이 체크를 할 때마다
해당 채팅방의 id를 반환하도록 설정해두었다.
id 정보는 해당 화면을 렌더링 할 때
아래와 같이 id가 포함된 채팅방 데이터를 불러오도록
로직을 만들어두었기 때문에
화면에 id값이 보이지 않아도 리액트에서
해당 데이터를 상태관리하고 있는 중이다.
자 그렇게 해서 리액트에 숨어있는 채팅방의 id값을
아래 코드와 같이 새롭게 상태관리 해주었다.
<Checkbox
onChange={() => {
setDel(Array.from(del));
if (del.includes(i.id)) {
setDel([...del.filter((item) => item !== i.id)]);
console.log(del);
} else {
setDel([i.id, ...del]);
console.log(del);
}
}}
/>
del 이라는 state에 체크한 채팅방의 id를 배열로 저장하도록 하였고
if문을 이용해 내가 체크한 채팅방의 id가 이미 del에 들어있다면
del에 들어있는 id를 제거하도록 로직을 만들었다.
조건문에서 내가 선택한 채팅방의 id가 이미 del에 저장되어 있는지 확인하는 로직은
자바스크립트에서 기본적으로 제공하는 includes 함수를 이용해서 구현했다.
배열.includes(찾을 값)
그럼 배열에 값이 있을 때 true를, 없으면 false를 반환해준다.
다음으로 filter 함수도 역시 자바스크립트에서 기본적으로 제공하는 함수인데
filter 함수는 원래 배열에서 내가 원하는 값만 골라서 새로운 배열을 만들어주는 함수다.
근데 아래와 같이 코드를 작성하면 내가 원하는 값만 빼고 새로운 배열을 만들어준다.
즉, 체크를 해제했을 때 체크가 해제된 채팅방의 id를 배열에서 제거해준다.
배열.filter((item)=>item !== 찾을값)
이게 머선 원리냐면 위에 보이는 item변수에는
배열에 포함된 값들이 순차적으로 할당된다.
그리고 순차적으로 할당된 값들을 찾을 값과 비교해서
동일하지 않은 값만 새로운 배열에 담아주는 것이다.
자 이렇게 해서 내가 삭제하고 싶은 채팅방의 id들이
del이라는 state에 배열로 저장되었다.
다음은 삭제 버튼에 onClick으로 실행할
deleteAll이라는 이름의 함수를 하나 만들어주었다.
const deleteAll = () => {
del.map(function (i, b) {
axios
.delete("http://localhost:8080/chat/rooms/" + i)
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
});
};
서버에 delete 요청을 할 때 여러개의 데이터를 한 번에 삭제하고 싶다면
2가지 방법으로 구현할 수 있다.
첫 번째는 프론트엔드에서 데이터의 수 만큼 axios.delete 요청을 하는 것
두 번째는 프론트에서 배열 형태로 데이터를 보내면 서버에서 순차적으로 삭제를 하는 것
나는 비효율적일 것 같지만 구현하기가 쉬울 것 같아서 첫 번째 방법을 선택했다.
삭제할 채팅방의 id가 배열 형태로 저장되어 있는 del에 map함수를 붙여서
서버에 순차적으로 axios.delete 요청을 보냈다.
요청에 대한 ㅇ답도 정상적으로 오는 것을 확인했다.
'코딩 > ReactJS' 카테고리의 다른 글
ReactJS에서 react-youtube 라이브러리로 유튜브 영상 제어하기 (0) | 2023.09.01 |
---|---|
react에서 댓글 기능 구현하기(선택된 컴포넌트만 댓글UI 보여주기) (0) | 2023.08.31 |
리액트에서 axios로 데이터 불러올 때 오류 핸들링하기 (0) | 2023.08.29 |
리액트에서 filter로 검색 기능 구현하기 (0) | 2023.08.28 |
리액트에서 게시글 목록 클릭해서 해당 게시글 상세 페이지로 이동하기 (0) | 2023.08.27 |