CreateComment(1)

김종민·2022년 5월 9일
0

insta-reactJS

목록 보기
21/27

들어가기
사진에 댓글다는 기능을 구현
createComment(1)에서는 useForm과 useMutaion을 이용해서 댓글 다는것을
구현하고 createComment(2)에서는 realTime, cache를 다루는 방법을 알아보자.


1. src/feed/Photo.js

Photo Component에서 Comments Components에 props로 보내주는 것만 확인!!!


  return (
    <div>
      <PhotoContainer key={id}>
        <PhotoHeader>
          <Avatar lg url={user.avatar} />
          <Username>{user.username}</Username>
        </PhotoHeader>
        <PhotoFile src={file} />
        <PhotoData>
          <PhotoActions>
            <div>
              <PhotoAction onClick={toggleLike}>
                <FontAwesomeIcon
                  style={{ color: isLiked ? 'tomato' : 'inherit' }}
                  size={'2x'}
                  icon={isLiked ? SolidHeart : faHeart}
                />
              </PhotoAction>
              <PhotoAction>
                <FontAwesomeIcon size={'2x'} icon={faComment} />
              </PhotoAction>
              <PhotoAction>
                <FontAwesomeIcon size={'2x'} icon={faPaperPlane} />
              </PhotoAction>
            </div>
            <div style={{ marginRight: '15px' }}>
              <FontAwesomeIcon size={'2x'} icon={faBookmark} />
            </div>
          </PhotoActions>
          <Likes>{likes === 1 ? '1 likes' : `${likes} likes`}</Likes>

**********************여기만 확인******************
          <Comments
            author={user.username}
            caption={caption}
            commentNumber={commentNumber}
            comments={comments}
            photoId={photoId}
          />
******************여기만 확인********************
        </PhotoData>
      </PhotoContainer>
    </div>
  )
}
export default Photo

2. src/feed/Comments.js

createComment(1)에서는 useMutation, useForm, react-form-hook사용만
확인하고, cache부분은 createComment(2)부분에서 확인할 것!!!
번호로 확인할 것.
react-hook-form과 useMutation을 같이 사용시에는 react-hook-form먼저 코딩할것.
번호 따라 갈것!

import { gql, useMutation } from '@apollo/client'
import styled from 'styled-components'
import Comment from './Comment'
import { useForm } from 'react-hook-form'
import useUser from '../../hooks/useUser'

const CREATE_COMMENT_MUTATION = gql`
  mutation createComment($photoId: Int!, $payload: String!) {
    createComment(photoId: $photoId, payload: $payload) {
      ok
      error
      id
    }
  }
`
///6. CREATE_COMMENT_MUTATION을 만들어서, server에서 실행시킬, mutation을 만든다.
///next, const [] = useMutation()으로 넘어간다~

const CommentsContainer = styled.div`
  margin-top: 20px;
`
const CommentCount = styled.span`
  opacity: 0.7;
  margin: 10px 0px;
  display: block;
  font-weight: 600;
  font-size: 15px;
`
const PostCommentContainer = styled.div`
  margin-top: 10px;
  padding-top: 15px;
  padding-bottom: 10px;
  border-top: 1px solid ${(props) => props.theme.borderColor};
`
const PostCommentInput = styled.input`
  width: 100%;
  font-size: 15px;
  &::placeholder {
    font-size: 15px;
  }
  &:hover {
    background-color: rgba(219, 219, 219, 0.3);
  }
`

function Comments({ author, photoId, caption, commentNumber, comments }) {
  const { data: userData } = useUser()
  const { register, handleSubmit, setValue, getValues } = useForm()
  ///3. useForm을 만듬,
  
  const createCommentUpdate = (cache, result) => {
    const { payload } = getValues()
    setValue('payload', '')
    const {
      data: {
        createComment: { ok, id },
      },
    } = result
    if (ok && userData?.me) {
      const newComment = {
        __typename: 'Comment',
        createdAt: Date.now() + '',
        id,
        isMine: true,
        payload,
        user: {
          ...userData.me,
        },
      }
      const newCacheComment = cache.writeFragment({
        data: newComment,
        fragment: gql`
          fragment BSName on Comment {
            id
            createdAt
            isMine
            payload
            user {
              username
              avatar
            }
          }
        `,
      })
      cache.modify({
        id: `Photo:${photoId}`,
        fields: {
          comments(prev) {
            return [...prev, newCacheComment]
          },
          commentNumber(prev) {
            return prev + 1
          },
        },
      })
    }
  }
  const [createCommentMutaiton, { loading }] = useMutation(
    CREATE_COMMENT_MUTATION,
    { update: createCommentUpdate }
  )
  ///7. const []=useMutation()을 만들어준다. update부분은 (2)에서 
  ///cache update할 수 있는 함수를 만든다.
  ///next, createComment mutation에서 comment id를 받아올 수 있게
  ///server부분을 수정한다(CREATE_COMMENT_MUTATION부분.)
  ///next, onValid부분으로 넘어가서 createCommentMutation에 variables를 넣어준다.
  
  const onValid = (data) => {
    const { payload } = data
    if (loading) {
      return
    }
    ///5. onValid 함수를 만든다. form으로부터 data를 받아와 {payload}, 즉, 댓글
    ///을 data로부터 payload를 받아온다.
    ///console.log로 data를 찍어봐도 됨, next, CREATE_COMMENT_MUTATION으로~

    
    createCommentMutaiton({
      variables: {
        photoId,
        payload,
      },
    })
    ///8. useMutation에서만든 createCommentMutation에 variables에
    ///photoId와 payload를 보내준다
    
  }
  return (
    <CommentsContainer>
      <Comment author={author} payload={caption} />
      <CommentCount>
        {commentNumber === 1 ? '1 comment' : `${commentNumber} comments`}
      </CommentCount>
      {comments?.map((comment) => (
        <Comment
          key={comment.id}
          author={comment.user.username}
          payload={comment.payload}
          id={comment.id}
          photoId={photoId}
          isMine={comment.isMine}
        />
      ))}
      <PostCommentContainer>
      ///1. 처음에 <div>로 만들었다가, styled.div로 PostCommentContainer만듬.
      ///위에서 확인할 것!
      
        <form onSubmit={handleSubmit(onValid)}>
          <PostCommentInput
          ///2. <input />로 만들었다가, 위에서 styled.input로 PostCommentInput 만듬.
          
            {...register('payload', { required: true, minLength: 5 })}
            type="text"
            placeholder="Write a comment.."
            
            ///4. ...register만들어서, useForm을 만든다..onSubmit={handleSubmit(onValid)}까지 만든다.
            ///next onValid함수
            
          />
        </form>
      </PostCommentContainer>
    </CommentsContainer>
  )
}

export default Comments

3. server/ createComment.typeDefs.js

return으로 id를 받아올 수 있게 넣는다!!

import { gql } from 'apollo-server'

export default gql`
  type CreateCommentResult {
    ok: Boolean!
    error: String
    id: Int
  }
  type Mutation {
    createComment(photoId: Int!, payload: String!): CreateCommentResult!
  }
`

4. server/ createComment.resolvers.js

import prisma from '../../client'
import { protectedResolver } from '../../users/users.util'

export default {
  Mutation: {
    createComment: protectedResolver(
      async (_, { photoId, payload }, { loggedInUser }) => {
        const ok = await prisma.photo.findUnique({
          where: { id: photoId },
          select: { id: true },
        })
        if (!ok) {
          return {
            ok: false,
            error: 'Photo not found',
          }
        }
        const newComment = await prisma.comment.create({
          data: {
            payload,
            photo: {
              connect: { id: photoId },
            },
            user: {
              connect: { id: loggedInUser.id },
            },
          },
        })
        ///newComment로 comment를 만들어서 return에 id: newComment.id로 return해준다.
        
        return {
          ok: true,
          id: newComment.id,
        }
        ///새로 만들어진 comment의 id를 return해준다.
        
      }
    ),
  },
}
profile
코딩하는초딩쌤

2개의 댓글

comment-user-thumbnail
2023년 11월 30일

Thank you for your insightful comments! I also want to share one of my favorite games with you guys. You can play this entertaining game alone or with friends. Give Retro Bowl it a shot you will love it!

답글 달기
comment-user-thumbnail
2024년 1월 10일

This watermelon game article is a ray of sunshine in written form. I appreciate the author's ability to uplift and motivate

답글 달기