들어가기
사진에 댓글다는 기능을 구현
createComment(1)에서는 useForm과 useMutaion을 이용해서 댓글 다는것을
구현하고 createComment(2)에서는 realTime, cache를 다루는 방법을 알아보자.
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
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
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!
}
`
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해준다.
}
),
},
}
This watermelon game article is a ray of sunshine in written form. I appreciate the author's ability to uplift and motivate
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!