카테고리 없음

Til (2023.02.27)

2023. 2. 28. 18:23

댓글 CRUD

 

커뮤니티 상세페이지의 댓글을 구현해 봤다.

조건은 상세페이지마다 각각의 다른 댓글이 있어야 하고, 쓰는 아이디의 이미지,닉네임,쓴날짜,수정,삭제이다.

useQuery와 useMutation을 이용해 만들었다.다시 해봐도 CRUD를 모두 사용해보기에는 댓글만한게 없는 것 같다.

댓글input옆에 등록버튼을 배치해 누르면 등록되게 해놨고 밑에 댓글창으로 출력되게 하였다.

최신댓글이 맨 위로 올라오게 하기위해 .reverse()를 사용했는데 렌더링될때마다 계속 반대로 바뀌는 오류가있어서 .slice().reverse()의 형태로 바꿔주었다. 빈칸일땐 작성이 안되게 예외 처리 해놨고, 수정 삭제는 본인이 쓴 댓글에만 표시되게 해놨다.

수정을 누르면 해당 댓글에 input창이 나오게 만들었고 취소를 누르면 다시 돌아오게만들었다.

삭제도 잘되고 수정완료를 누르면 잘 수정 되었다. crud를 몇달동안 매일 하다보니 이제는 만드는 속도가 많이 빨라졌다.

import React from "react";
import styled from "styled-components";
import { useState } from "react";
import axios from "axios";
import { useMutation } from "react-query";
import { v4 as uuidv4 } from "uuid";
import { useQuery } from "react-query";
import { useQueryClient } from "react-query";

function Comment({ PostId }: any) {
  const queryClient = useQueryClient();

  const myId = sessionStorage.getItem("steamid");
  const myNickName = sessionStorage.getItem("nickName");
  const ProfileImgUrl: any = sessionStorage.getItem("profileimg");

  const [commentInput, setCommentInput] = useState<string>("");
  const [editOn, setEditOn] = useState<string>("");
  const [editInput, setEditInput] = useState<string>("");

  const newDate = new Date();
  const year = newDate.getFullYear();
  const month = newDate.getMonth() + 1;
  const day = newDate.getDate();
  const date = `${year}.${month}.${day}`;

  const getComment = async () => {
    const response = await axios.get("http://localhost:3001/comment");
    return response;
  };
  const { data } = useQuery("comment", getComment);
  const comment = data?.data.slice().reverse();
  const commentFilter = comment?.filter((i: any) => {
    return i.postId === PostId;
  });

  const postMutation = useMutation(
    (newComment: object) =>
      axios.post("http://localhost:3001/comment", newComment),
    {
      onSuccess: () => {
        queryClient.invalidateQueries("comment");
      },
    }
  );

  const DeleteMutation = useMutation(
    (id) => axios.delete(`http://localhost:3001/comment/${id}`),
    {
      onSuccess: () => {
        queryClient.invalidateQueries("comment");
      },
    }
  );

  const EditMutation = useMutation(
    (editComment: any) =>
      axios.put(`http://localhost:3001/comment/${editComment.id}`, editComment),
    {
      onSuccess: () => {
        queryClient.invalidateQueries("comment");
      },
    }
  );

  const CommentInputOnChange = (e: any) => {
    setCommentInput(e.target.value);
  };

  const CommentFormonSubmit = (e: any) => {
    e.preventDefault();
    if (commentInput === "") {
      alert("빈칸은 안됨");
      return;
    }

    const newComment = {
      id: uuidv4(),
      postId: PostId,
      myId: myId,
      name: myNickName,
      date: date,
      profileImg: ProfileImgUrl,
      contents: commentInput,
    };

    postMutation.mutate(newComment);

    setCommentInput("");
  };

  const DeleteOnClick = (id: any) => {
    DeleteMutation.mutate(id);
  };

  const EditInputOnChange = (e: any) => {
    setEditInput(e.target.value);
  };

  const EditCommentButton = (id: any) => {
    if (editInput === "") {
      alert("빈칸은 안됨");
      return;
    } else {
      const editComment = {
        ...comment.find((i: any) => i.id === id),
        date: date + " " + "수정",
        contents: editInput,
      };
      EditMutation.mutate(editComment);

      setEditInput("");
      setEditOn("");
    }
  };

  return (
    <CommentWrap>
      <h1>댓글</h1>
      {/* 댓글 입력칸 */}
      <CommentForm onSubmit={CommentFormonSubmit}>
        <CommentInput value={commentInput} onChange={CommentInputOnChange} />
        <CommentFormButton>등록</CommentFormButton>
      </CommentForm>
      {/* 댓글 창 */}
      {commentFilter?.map((i: any) => {
        return (
          <CommentContents>
            <CommentImg src={i.profileImg} />
            <CommentName>{i.name}</CommentName>
            {editOn === i.id ? (
              <EditInput
                placeholder={i.contents}
                value={editInput}
                onChange={EditInputOnChange}
              />
            ) : (
              <CommentText>{i.contents}</CommentText>
            )}
            <CommentDate>{i.date}</CommentDate>

            {editOn === i.id ? (
              <>
                <CommentEdit onClick={() => EditCommentButton(i.id)}>
                  완료
                </CommentEdit>
                <CommentDelete onClick={() => setEditOn("")}>
                  취소
                </CommentDelete>
              </>
            ) : (
              <>
                {i.myId === myId ? (
                  <>
                    <CommentEdit
                      onClick={() => {
                        setEditOn(i.id);
                      }}
                    >
                      수정
                    </CommentEdit>
                    <CommentDelete onClick={() => DeleteOnClick(i.id)}>
                      삭제
                    </CommentDelete>
                  </>
                ) : (
                  ""
                )}
              </>
            )}
          </CommentContents>
        );
      })}
    </CommentWrap>
  );
}

export default Comment;
const CommentWrap = styled.div`
  width: 80%;
  margin: 0 auto;
`;
const CommentForm = styled.form`
  margin-top: 20px;
  margin-bottom: 50px;
  width: 100%;
  height: 40px;
`;
const CommentInput = styled.input`
  width: 95%;
  height: 40px;
`;
const CommentFormButton = styled.button`
  width: 5%;
  height: 40px;
  background-color: #000;
  color: #fff;
`;
const CommentContents = styled.div`
  border-top: 1px solid #000;
  display: flex;
  height: 60px;
  align-items: center;
`;
const CommentImg = styled.img`
  width: 40px;
  height: 40px;
  border-radius: 50%;
`;
const CommentName = styled.h2`
  margin: 10px 0 auto 10px;
`;
const EditInput = styled.input`
  margin: auto 0 15px 50px;
`;
const CommentText = styled.p`
  margin: auto 0 15px 50px;
`;
const CommentDate = styled.p`
  margin: auto 0 15px auto;
`;
const CommentEdit = styled.button`
  margin-left: 10px;
  margin-bottom: auto;
  font-size: 16px;
  color: blue;
`;
const CommentDelete = styled.button`
  margin-bottom: auto;
  margin-left: 10px;
  font-size: 16px;
  color: blue;
`;
저작자표시 (새창열림)
prdg
prdg
prdg
신정근 개발일지
prdg
전체
오늘
어제
  • 분류 전체보기 (89)
    • 프로젝트 (3)
    • 프로그래머스 (2)
    • 블록체인 (2)
    • 리액트 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 구조분해할당
  • ReactNative
  • Blockchain
  • touchableopacity
  • SafeAreaView
  • TODOLIST
  • Recoil
  • TypeScript
  • 리액트
  • JavaScript
  • ReactQuery
  • Node
  • state
  • react
  • node.js
  • usemutation
  • socket.io
  • 프로그래머스
  • Props
  • 블록체인

최근 댓글

최근 글

hELLO · Designed By 정상우.
prdg
Til (2023.02.27)
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.