[TIL] 230710

이세령·2023년 7월 10일
0

TIL

목록 보기
52/118

이벤트 버블링 방지하기

카드 내에 존재하는 삭제 버튼이 눌렸을 때 카드의 이동하는 동작을 막고 싶었다.
stopPropagation() 으로 막는 방법

<DeleteCard
            onClick={(e) => {
              e.stopPropagation();
              console.log("삭제");
            }}
          >
            <MdDeleteForever size="25" style={{}}></MdDeleteForever>
          </DeleteCard>

카드와 같은 부모요소를 가지도록(?) 나란히 작성해주고 부모요소가 static 외의 position을 가지고 있을 때 position: absolute로 위치를 지정할 수 있다.

<CardBox done={`${study.isDone}`}>
      <div
        onClick={() => {
          navigate(`/detailstudy/${study.id}`);
        }}
      >
        <CardNav>
          <div>작성자 {study.writer}</div>
        </CardNav>
        <Cardcontext>{study.title}</Cardcontext>
      </div>
      <MdDeleteForever
        size="25"
        onClick={() => console.log("삭제")}
        style={{ position: "absolute", top: "10px", right: "10px" }}
      ></MdDeleteForever>
      <Cardfooter>
        <div>
          <Button>{study.isDone ? "완료" : "미완료"}</Button>
        </div>
      </Cardfooter>
    </CardBox>

삭제 기능

CardList에서 prop으로 study라는 item을 내려보냈으니 study.id를 하면 해당 카드의 id를 알 수 있다!
이를 이용해서 클릭한 Card를 삭제하는 동작을 코딩했다.

const navigate = useNavigate();

  const queryClient = useQueryClient();

  const mutation = useMutation(deleteStudy, {
    onSuccess: () => {
      queryClient.invalidateQueries("study");
      console.log("Delete 성공");
    },
  });

  const findCardId = (e) => {
    if (window.confirm("정말 삭제하시겠습니까??")) {
      //확인
      mutation.mutate(study.id);
      alert("삭제되었습니다!");
    } else {
      return false;
    }
  };

detail페이지에서도 삭제기능을 동작해야 하고 코멘트도 삭제하는 기능이 필요하니 customhook으로 빼는 시도를 해봤다.

Card.jsx

const [deleteStudyMutation] = useDelete();

  const findCardId = (e) => {
    if (window.confirm("정말 삭제하시겠습니까??")) {
      //확인
      deleteStudyMutation.mutate(study.id);
      alert("삭제되었습니다!");
    } else {
      return false;
    }
  };

useDelete

import { useMutation, useQueryClient } from "react-query";
import { deleteStudy } from "../api/studyTodo";

const useDelete = () => {
  const queryClient = useQueryClient();
  const deleteStudyMutation = useMutation(deleteStudy, {
    onSuccess: () => {
      queryClient.invalidateQueries("study");
      console.log("Delete 성공");
    },
  });

  return [deleteStudyMutation];
};

export default useDelete;

코드 리팩토링 하기

1. input을 customhook으로 만들어서 코드를 줄일 수 있다.
2. queryClient와 mutation을 사용하는 코드를 customhook으로 줄일 수 있을 것 같다.
3. useNavigate를 사용하는 곳도 customhook으로 만들어서 줄일 수 있을 것 같다.

완료/미완료 patch

studyTodo.js

const updateComplete = async (newComplete) => {
  const response = await axios.patch(
    `${process.env.REACT_APP_SERVER_URL}/study/${newComplete.id}`,
    { isDone: newComplete.isDone }
  );
};

Button.jsx

const queryClient = useQueryClient();
  const updateCompleteMutation = useMutation(updateComplete, {
    onSuccess: () => {
      queryClient.invalidateQueries("study");
    },
  });

const basicButtonHandler = (role) => {
    if (role === "complete") {
      const newComplete = { id: props.cardKey, isDone: !props.complete };
      updateCompleteMutation.mutate(newComplete);
    } else if (role === "filter") {
      console.log("filter 및 정렬");
    }
  };

id와 새 내용을 인자로 넘겨서 값을 patch 해주었다.

새 글 작성시 오류

detail페이지로 들어가면 코멘트가 db가 빈 값으로라도 생성되지 않기 때문에 오류가 발생하는 것 같다.
먼저, DetailTodo.jsx에서 오류 처리를 해주었다.
DetailTodo.jsx

return (
    <>
      <Header />
      <DetailBox>
        <h1>{`${study.title}`}</h1>
        <div>
          <div>{`작성자: ${study.writer}`}</div>
          <Button>수정</Button>
          <Button>삭제</Button>
        </div>
        <div>{`완료 여부: ${study.isDone}`}</div>
        <div>{`내용 : ${study.contents}`}</div>
      </DetailBox>
      {comments ? (
        <DetailBox>
          {comments.userComments?.map((comment) => (
            <Comments codata={comment} key={comment.user} />
          ))}
        </DetailBox>
      ) : coisError ? (
        <p>댓글 오류가 발생하였습니다!!</p>
      ) : coisLoading ? (
        <p>댓글 로딩중</p>
      ) : (
        <p>댓글을 불러오지 못했습니다.</p>
      )}

      <Footer />
    </>
  );

React에서 confirm 사용

window.confirm

Detail 수정하기 기능

입력할 수 있는 공간 만들기 -> state를 하나 만들어서 true일 때 입력창 보여주기(기존 제목과 내용을 set) -> 저장 버튼을 눌렀을 때, db 업데이트 해주기

<>
      <Header />
      <DetailBox>
        {!updateState && (
          <>
            <h1>{`${study.title}`}</h1>
            <div>
              <div>{`작성자: ${study.writer}`}</div>

              <Button
                onClick={() => {
                  setUpdateState(true);
                  setUpdateTitle(study.title);
                  setUpdateContent(study.contents);
                }}
              >
                수정
              </Button>
              <Button>삭제</Button>
            </div>
            <div>{`완료 여부: ${study.isDone}`}</div>
            <div>{`내용 : ${study.contents}`}</div>
            {comments ? (
              <div>
                {comments.userComments?.map((comment) => (
                  <Comments codata={comment} key={comment.user} />
                ))}
              </div>
            ) : coisError ? (
              <p>댓글을 불러오지 못했습니다.</p>
            ) : coisLoading ? (
              <p>댓글 로딩중</p>
            ) : null}
          </>
        )}
        {updateState && (
          <>
            <div>
              <label>제목</label>
              <input value={updateTitle} onChange={updateTitleHandler} />
            </div>
            <div>
              <label>내용</label>
              <textarea value={updateContent} onChange={updateContentHandler} />
            </div>
            <Button
              role={"update"}
              update={newStudy}
              onClick={() => {
                setUpdateState(!updateState);
                console.log("저장");
              }}
            >
              저장
            </Button>
          </>
        )}
      </DetailBox>

      <Footer />
    </>

Button.jsx
전체 리스트와 상세 페이지 모두 변경되어야 하기 때문에 2가지를 무효화 해줬다.

// 게시글 업데이트
  const updateDetailMutation = useMutation(updateStudy, {
    onSuccess: () => {
      queryClient.invalidateQueries("study");
      queryClient.invalidateQueries(`${props.update.id}`);
    },
  });

// 동작되는 곳
<ButtonStyle
        onClick={() => {
          basicButtonHandler(props.role);
          props.onClick();
        }}
      >
        {props.children}
      </ButtonStyle>

Put 과 Patch의 차이

Put - 리소스의 모든 것을 업데이트 한다.
Patch - 리소스의 일부를 업데이트 한다.

오늘 통신 관련 작업을 많이 해보면서 axios와 좀 더 친숙해진 것 같다. 코멘트 로딩의 경우 따로 오류 처리를 해줬고 할 작업이 많은 update를 구현했고 댓글의 수정/삭제만 구현하면 필수 요구사항은 종료된다.

profile
https://github.com/Hediar?tab=repositories

0개의 댓글