댓글(등록) 기능 1차

순9·2023년 11월 28일
0

리액트 게시판

목록 보기
41/54

구현 해야할 목록
1. 사용자 별 댓글 등록
2. 답 댓글
3. 사용자 별 댓글 수정/ 삭제

page컴포넌트에서 댓글 등록 구현
Comment컴포넌트

page component

const userComments = useSelector(
    (state: any) => state.boardPageComment.boardComment
  );
  const userPageComment = userComments[boardId];
  
  return(
   <Comment userPageComment={userPageComment} />
  );

state에서 commentSlice 가져온 후 페이지 id 적용

Comment component

전체 코드

import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import userComment from "../../redux/thunks/boardCommentThunk";
import { getAuth } from "firebase/auth";
import { useParams } from "react-router-dom";

const Comment = (props: any) => {
  //댓글 내용
  const [content, setConent] = useState("");

  //사용자 정보
  const auth = getAuth();
  const currentUser = auth.currentUser;
  const userId = currentUser?.uid;

  const dispatch = useDispatch();

  const selectedBoardId = useSelector(
    (state: any) => state.board.selectedBoardId
  );
  const userNicNameList = useSelector((state: any) => state.login.userLists);
  const userInformation = useSelector((state: any) => state.login.user);
  const userNicName = userInformation.displayName;

//댓글 등록 
  const handleComment = async (e: any) => {
    e.preventDefault();

    // if (!!content) {
    //   window.confirm("댓글 내용을 입력 해주세요");
    //   return;
    // }

    const comment = {
      content: content,
      userUid: userId as string,
      timedata: new Date(),
      displayName: userNicName,
    };

    await dispatch(
      userComment({
        boardId: selectedBoardId,
        boardComment: comment,
      }) as any
    );
    setConent("");
  };

 
  const objectComment = Object.values(props);
  return (
    <div className="comment_box">
      <form onSubmit={handleComment}>
        <textarea
          value={content}
          maxLength={300}
          onChange={(e) => {
            setConent(e.target.value);
          }}
          placeholder="내용을 입력 해주세요"
        />
        <input type="submit" value="등록" />
      </form>

      <div className="comment_view">
        <div className="comment_user">
          <ul>
            {objectComment.map((items: any, index: number) =>
              items.map((item: any, innerIndex: number) => {
                return (
                  <li key={index}>
                    <span>{item.displayName}</span>
                    <span>{item.timedata}</span>
                    <div>{item.content}</div>
                    <div className="comment_txt">
                      <div className="comment_btn">
                        <input type="submit" value="댓글" />
                        <input type="submit" value="수정" />
                        <input type="button" value="삭제" />
                      </div>
                    </div>
                  </li>
                );
              })
            )}
          </ul>
        </div>
      </div>
    </div>
  );
};

export default Comment;

파이어베이스와 slice 연동 데이터가 등록 되는 것 확인

Slice

import { createSlice } from "@reduxjs/toolkit";
import userComment from "../thunks/boardCommentThunk";

interface CommentType {
  content: string;
  userUid: string;
  timedata: Date;
  displayName: string;
}

interface MyComment {
  boardComment: Record<number, CommentType[]>;
}

const initialState: MyComment = {
  boardComment: {},
};

const boardPageComment = createSlice({
  name: "pageComment",
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(userComment.pending, (state, action) => {
        console.log(`비동기 댓글 요청 중`);
      })
      .addCase(userComment.fulfilled, (state, action) => {
        console.log(`비동기 댓글 요청 성공`);
        //1.
        const { boardId, boardComment: pageComment } = action.payload;
		//2.
        const comment = state.boardComment[boardId] || [];
		//3.
        const newComment = [...comment, pageComment];
		//4.
        state.boardComment[boardId] = newComment;
      })
      .addCase(userComment.rejected, (state, action) => {
        console.log(`비동기 댓글 실패`);
      });
  },
});

export default boardPageComment.reducer;
  1. 비구조 할당 형식으로 각각 데이터를 받아 온다
  2. 받아온 데이터를 comment 변수에 담는다
  3. newComment변수에 기존 값과 새로 추가되는 값을 넣는다
  4. 선택되어 있는 state에 3번 추가

Thunk

import { createAsyncThunk } from "@reduxjs/toolkit";
import { firestore } from "../../firebase";
import {
  addDoc,
  setDoc,
  collection,
  getDocs,
  getDoc,
  doc,
} from "firebase/firestore";
import { getAuth } from "firebase/auth";

interface CommentType {
  content: string;
  userUid: string;
  timedata: Date;
  displayName: string;
}

const userComment = createAsyncThunk<
  { boardId: number; boardComment: CommentType },
  { boardId: number; boardComment: CommentType }
>("user/comment", async (data, thunkAPI) => {
  try {
    const { boardId, boardComment } = data;
    const { content } = boardComment;

    const auth = getAuth();
    const currentUser = auth.currentUser;
    const userId = currentUser?.uid;

    const state: any = thunkAPI.getState();
    const boardSelectedId = state.board.selectedBoardId;
    const strId = data.boardId.toString();
    const userNicNameList = state.login.userLists;
    const userInformation = state.login.user;
    const userNicName = userInformation.displayName;

    console.log(userNicName);

    //컬렉션
    const userCollection = collection(firestore, "users");
    //도큐멘트
    const userDocRef = doc(userCollection, "userData");
    //컬렉션>도큐멘트>userId이름을 가진 하위 컬렉션
    const subCollectionRef = collection(userDocRef, strId);
    //하위 컬렌션이 가진 모든 하위 도큐멘트 출력 getDocs사용
    const specificDoc = await getDocs(subCollectionRef);

    for (const [index, docI] of specificDoc.docs.entries()) {
      const data = docI.data();
      const dataId = data.did;
      const dataIndex = data.index;

      //하위 도큐멘트
      const docRef = doc(subCollectionRef, dataIndex);

      //하위 컬렉션
      const lastCallectionRef = collection(docRef, "comment");

      if (boardSelectedId === dataId) {
        // const underSetDoc = doc(lastCallectionRef, userId as string);

        await addDoc(lastCallectionRef, {
          content: content,
          userUid: userId,
          timedata: new Date(),
          displayName: userNicName,
        });
      } else {
        console.log("댓글 오류------------------");
      }
    }
    const responseDataComment = {
      boardId: boardSelectedId,
      boardComment: {
        content: content,
        userUid: userId as string,
        timedata: new Date(),
        displayName: userNicName,
      },
    };
    return responseDataComment;
  } catch (error) {
    throw error;
  }
});

export default userComment;

참고
entries
Object.values

profile
1. 사용법 익히기 2. 원리가 뭔지 찾아보기 3. 원리를 공부하기

0개의 댓글