From 8a56d59c9746a85c1562781a20310b7f7cf191ab Mon Sep 17 00:00:00 2001 From: ontheway-01 Date: Wed, 27 Mar 2024 13:16:40 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20reply=20comment=20UI=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20-=20flickering=20=EC=98=A4=EB=A5=98=20=EA=B3=A0?= =?UTF-8?q?=EC=B9=98=EA=B8=B0=20=20(#112)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/board/postDetail/PostDetailPage.tsx | 6 +- .../Comment/CommentCardContainer.tsx | 21 ++-- .../components/Comment/PostReplyComments.tsx | 64 ++++++++++ .../Comment/ReplyCommentContainer.tsx | 34 ++++++ .../postDetail/components/Comment/styled.ts | 16 +++ .../CommentInput/CommentInputContainer.tsx | 11 +- .../ReplyComment/PostReplyComments.tsx | 114 +++++++++--------- .../ReplyComment/ReplyCommentContainer.tsx | 58 ++++----- .../components/ReplyComment/index.ts | 2 +- .../components/ReplyComment/styled.ts | 30 ++--- .../board/postDetail/components/index.ts | 2 +- yarn.lock | 22 +++- 12 files changed, 250 insertions(+), 130 deletions(-) create mode 100644 src/pages/board/postDetail/components/Comment/PostReplyComments.tsx create mode 100644 src/pages/board/postDetail/components/Comment/ReplyCommentContainer.tsx diff --git a/src/pages/board/postDetail/PostDetailPage.tsx b/src/pages/board/postDetail/PostDetailPage.tsx index 3138add4..3ba3510e 100644 --- a/src/pages/board/postDetail/PostDetailPage.tsx +++ b/src/pages/board/postDetail/PostDetailPage.tsx @@ -8,7 +8,7 @@ import { PostAuthor, PostComments, PostDetailMenu, - PostReplyComments, + // PostReplyComments, } from './components'; import { CommentDeleteModal } from './components/CommentDeleteModal'; import { PostDeleteModal } from './components/PostDeleteModal'; @@ -61,7 +61,7 @@ const PostDetailPage: React.FC = observer(() => { {post.commentCount} - + {/* */} @@ -72,7 +72,7 @@ const PostDetailPage: React.FC = observer(() => { <>{/* TODO: 페이지 스켈레톤 */} )} - + {/* */} ); diff --git a/src/pages/board/postDetail/components/Comment/CommentCardContainer.tsx b/src/pages/board/postDetail/components/Comment/CommentCardContainer.tsx index 27ffa03a..7ca44d48 100644 --- a/src/pages/board/postDetail/components/Comment/CommentCardContainer.tsx +++ b/src/pages/board/postDetail/components/Comment/CommentCardContainer.tsx @@ -5,6 +5,7 @@ import { generatePath, useHistory, useParams } from 'react-router-dom'; import { useLongPress } from 'use-long-press'; import { CommentCardView } from './CommentCardView'; +import { PostReplyComments } from './PostReplyComments'; import { ReplyLink } from './styled'; import { InputState } from '../CommentInput'; @@ -43,23 +44,19 @@ export const CommentCardContainer: React.FC = observer( onFinish: ev => ev?.preventDefault(), }); - const handleGoReply = useCallback( - (params: PostParams, target?: Model.Comment | Model.ReplyComment) => () => { - if (!target) return; + // const handleGoReply = useCallback( + // (params: PostParams, target?: Model.Comment | Model.ReplyComment) => () => { + // if (!target) return; - replace(generatePath(PAGE_URL.PostReplyComment, { ...params, commentId: target.id })); - }, - [], - ); + // replace(generatePath(PAGE_URL.PostReplyComment, { ...params, commentId: target.id })); + // }, + // [], + // ); return (
  • - {withReplyLink && model.numChildComment ? ( - - 답글 {model.numChildComment}개 더보기 - - ) : null} + {model.numChildComment != 0 ? : null}
  • ); }, diff --git a/src/pages/board/postDetail/components/Comment/PostReplyComments.tsx b/src/pages/board/postDetail/components/Comment/PostReplyComments.tsx new file mode 100644 index 00000000..606c80d5 --- /dev/null +++ b/src/pages/board/postDetail/components/Comment/PostReplyComments.tsx @@ -0,0 +1,64 @@ +import { observer } from 'mobx-react-lite'; +import { useCallback, useEffect, useRef } from 'react'; +import { generatePath, useHistory, useParams } from 'react-router-dom'; +import { Virtuoso } from 'react-virtuoso'; + +import { ReplyCommentContainer } from './ReplyCommentContainer'; +import { BackLink, ReplyCommentsBox } from './styled'; +import { CommentCard } from '../Comment'; + +import { PAGE_URL, PostParams } from '@/configs/path'; +import { usePageUiStore } from '@/hooks'; + +export const PostReplyComments: React.FC<{ model: Model.Comment }> = observer(({ model }) => { + //const { boardId, postId, commentId } = useParams(); + //const { replace } = useHistory(); + const { + setVirtuosoRef, + screenRef, + replyComments: { fetch, reset, parent, comments, hasMore, page }, + commentInput: { resetState }, + } = usePageUiStore(); + + // const handleBack = useCallback( + // () => replace(generatePath(PAGE_URL.PostDetail, { boardId, postId })), + // [boardId, postId], + // ); + + const virtuoso = useRef(null); + const timer = useRef(); + const loadMore = useCallback( + (hasMore: boolean, page: number) => () => { + if (timer.current) clearTimeout(timer.current); + if (hasMore) timer.current = setTimeout(() => fetch(model.id, page + 1), 50); + }, + [model.postId], + ); + + useEffect(() => { + setVirtuosoRef(virtuoso); + }, [parent]); + + useEffect(() => { + fetch(model.id); + + return () => { + reset(); + resetState(); + }; + }, [model.id]); + + return parent ? ( + + } + /> + + ) : null; +}); diff --git a/src/pages/board/postDetail/components/Comment/ReplyCommentContainer.tsx b/src/pages/board/postDetail/components/Comment/ReplyCommentContainer.tsx new file mode 100644 index 00000000..659b2c5f --- /dev/null +++ b/src/pages/board/postDetail/components/Comment/ReplyCommentContainer.tsx @@ -0,0 +1,34 @@ +import { computed } from 'mobx'; +import { observer } from 'mobx-react-lite'; +import { useCallback, useRef } from 'react'; +import { useLongPress } from 'use-long-press'; + +import { CommentCardView } from './CommentCardView'; +import { Li } from './styled'; +import { InputState } from '../CommentInput'; + +import { usePageUiStore } from '@/hooks'; + +export const ReplyCommentContainer: React.FC<{ model: Model.Comment }> = observer(({ model }) => { + const ref = useRef(null); + const { + commentInput, + commentMenuModal: { open }, + } = usePageUiStore(); + const state = computed(() => + commentInput.target?.id === model.id ? commentInput.state : InputState.WRITE, + ).get(); + + const handleLongPress = useCallback(model => () => open(model), [open]); + const bind = useLongPress(handleLongPress(model), { + cancelOnMovement: true, + captureEvent: true, + onFinish: ev => ev?.preventDefault(), + }); + + return ( +
  • + +
  • + ); +}); diff --git a/src/pages/board/postDetail/components/Comment/styled.ts b/src/pages/board/postDetail/components/Comment/styled.ts index 7a6cdc1c..37aaa515 100644 --- a/src/pages/board/postDetail/components/Comment/styled.ts +++ b/src/pages/board/postDetail/components/Comment/styled.ts @@ -70,3 +70,19 @@ export const ReplyLink = styled(ClearButton)` font-size: 11px; line-height: 13px; `; + +export const ReplyCommentsBox = styled(ClearUl)` + margin-top: 10px; + padding: 5px -0; + border-top: 1px solid #f5f5f5; +`; + +export const BackLink = styled(ClearButton)` + padding: 5px 4px; + font-size: 11px; + line-height: 13px; +`; + +export const Li = styled.li` + padding: 0 0 5px 15px; +`; diff --git a/src/pages/board/postDetail/components/CommentInput/CommentInputContainer.tsx b/src/pages/board/postDetail/components/CommentInput/CommentInputContainer.tsx index 67c39957..20457574 100644 --- a/src/pages/board/postDetail/components/CommentInput/CommentInputContainer.tsx +++ b/src/pages/board/postDetail/components/CommentInput/CommentInputContainer.tsx @@ -16,7 +16,8 @@ import { useRootStore } from '@/stores'; type FormBody = { content: string }; export const CommentInputContainer: React.FC = observer(() => { - const isReplyComment = !!useRouteMatch(PAGE_URL.PostReplyComment); + //const isReplyComment = !!useRouteMatch(PAGE_URL.PostReplyComment); + const { postId } = useParams(); const { ui: { alert }, @@ -76,11 +77,9 @@ export const CommentInputContainer: React.FC = observer(() => { return ( ); diff --git a/src/pages/board/postDetail/components/ReplyComment/PostReplyComments.tsx b/src/pages/board/postDetail/components/ReplyComment/PostReplyComments.tsx index e6548ab8..31af60a6 100644 --- a/src/pages/board/postDetail/components/ReplyComment/PostReplyComments.tsx +++ b/src/pages/board/postDetail/components/ReplyComment/PostReplyComments.tsx @@ -1,66 +1,66 @@ -import { observer } from 'mobx-react-lite'; -import { useCallback, useEffect, useRef } from 'react'; -import { generatePath, useHistory, useParams } from 'react-router-dom'; -import { Virtuoso } from 'react-virtuoso'; +// import { observer } from 'mobx-react-lite'; +// import { useCallback, useEffect, useRef } from 'react'; +// import { generatePath, useHistory, useParams } from 'react-router-dom'; +// import { Virtuoso } from 'react-virtuoso'; -import { ReplyCommentContainer } from './ReplyCommentContainer'; -import { BackLink, CommentsBox } from './styled'; -import { CommentCard } from '../Comment'; +// import { ReplyCommentContainer } from './ReplyCommentContainer'; +// import { BackLink, CommentsBox } from './styled'; +// import { CommentCard } from '../Comment'; -import { PAGE_URL, PostParams } from '@/configs/path'; -import { usePageUiStore } from '@/hooks'; +// import { PAGE_URL, PostParams } from '@/configs/path'; +// import { usePageUiStore } from '@/hooks'; -export const PostReplyComments: React.FC = observer(() => { - const { boardId, postId, commentId } = useParams(); - const { replace } = useHistory(); - const { - setVirtuosoRef, - screenRef, - replyComments: { fetch, reset, parent, comments, hasMore, page }, - commentInput: { resetState }, - } = usePageUiStore(); +// export const PostReplyComments: React.FC = observer(() => { +// const { boardId, postId, commentId } = useParams(); +// const { replace } = useHistory(); +// const { +// setVirtuosoRef, +// screenRef, +// replyComments: { fetch, reset, parent, comments, hasMore, page }, +// commentInput: { resetState }, +// } = usePageUiStore(); - const handleBack = useCallback( - () => replace(generatePath(PAGE_URL.PostDetail, { boardId, postId })), - [boardId, postId], - ); +// const handleBack = useCallback( +// () => replace(generatePath(PAGE_URL.PostDetail, { boardId, postId })), +// [boardId, postId], +// ); - const virtuoso = useRef(null); - const timer = useRef(); - const loadMore = useCallback( - (hasMore: boolean, page: number) => () => { - if (timer.current) clearTimeout(timer.current); - if (hasMore) timer.current = setTimeout(() => fetch(commentId, page + 1), 50); - }, - [postId], - ); +// const virtuoso = useRef(null); +// const timer = useRef(); +// const loadMore = useCallback( +// (hasMore: boolean, page: number) => () => { +// if (timer.current) clearTimeout(timer.current); +// if (hasMore) timer.current = setTimeout(() => fetch(commentId, page + 1), 50); +// }, +// [postId], +// ); - useEffect(() => { - setVirtuosoRef(virtuoso); - }, [parent]); +// useEffect(() => { +// setVirtuosoRef(virtuoso); +// }, [parent]); - useEffect(() => { - fetch(commentId); +// useEffect(() => { +// fetch(commentId); - return () => { - reset(); - resetState(); - }; - }, [commentId]); +// return () => { +// reset(); +// resetState(); +// }; +// }, [commentId]); - return parent ? ( - - 전체 댓글로 이동하기 - - } - /> - - ) : null; -}); +// return parent ? ( +// +// 전체 댓글로 이동하기 +// +// } +// /> +// +// ) : null; +// }); diff --git a/src/pages/board/postDetail/components/ReplyComment/ReplyCommentContainer.tsx b/src/pages/board/postDetail/components/ReplyComment/ReplyCommentContainer.tsx index 037145c1..cd205805 100644 --- a/src/pages/board/postDetail/components/ReplyComment/ReplyCommentContainer.tsx +++ b/src/pages/board/postDetail/components/ReplyComment/ReplyCommentContainer.tsx @@ -1,34 +1,34 @@ -import { computed } from 'mobx'; -import { observer } from 'mobx-react-lite'; -import { useCallback, useRef } from 'react'; -import { useLongPress } from 'use-long-press'; +// import { computed } from 'mobx'; +// import { observer } from 'mobx-react-lite'; +// import { useCallback, useRef } from 'react'; +// import { useLongPress } from 'use-long-press'; -import { Li } from './styled'; -import { CommentCardView } from '../Comment'; -import { InputState } from '../CommentInput'; +// import { Li } from './styled'; +// import { CommentCardView } from '../Comment'; +// import { InputState } from '../CommentInput'; -import { usePageUiStore } from '@/hooks'; +// import { usePageUiStore } from '@/hooks'; -export const ReplyCommentContainer: React.FC<{ model: Model.Comment }> = observer(({ model }) => { - const ref = useRef(null); - const { - commentInput, - commentMenuModal: { open }, - } = usePageUiStore(); - const state = computed(() => - commentInput.target?.id === model.id ? commentInput.state : InputState.WRITE, - ).get(); +// export const ReplyCommentContainer: React.FC<{ model: Model.Comment }> = observer(({ model }) => { +// const ref = useRef(null); +// const { +// commentInput, +// commentMenuModal: { open }, +// } = usePageUiStore(); +// const state = computed(() => +// commentInput.target?.id === model.id ? commentInput.state : InputState.WRITE, +// ).get(); - const handleLongPress = useCallback(model => () => open(model), [open]); - const bind = useLongPress(handleLongPress(model), { - cancelOnMovement: true, - captureEvent: true, - onFinish: ev => ev?.preventDefault(), - }); +// const handleLongPress = useCallback(model => () => open(model), [open]); +// const bind = useLongPress(handleLongPress(model), { +// cancelOnMovement: true, +// captureEvent: true, +// onFinish: ev => ev?.preventDefault(), +// }); - return ( -
  • - -
  • - ); -}); +// return ( +//
  • +// +//
  • +// ); +// }); diff --git a/src/pages/board/postDetail/components/ReplyComment/index.ts b/src/pages/board/postDetail/components/ReplyComment/index.ts index 0d2c6671..466daea1 100644 --- a/src/pages/board/postDetail/components/ReplyComment/index.ts +++ b/src/pages/board/postDetail/components/ReplyComment/index.ts @@ -1 +1 @@ -export { PostReplyComments } from './PostReplyComments'; +// export { PostReplyComments } from './PostReplyComments'; diff --git a/src/pages/board/postDetail/components/ReplyComment/styled.ts b/src/pages/board/postDetail/components/ReplyComment/styled.ts index 68183d20..2cb0650c 100644 --- a/src/pages/board/postDetail/components/ReplyComment/styled.ts +++ b/src/pages/board/postDetail/components/ReplyComment/styled.ts @@ -1,19 +1,19 @@ -import styled from '@emotion/styled'; +// import styled from '@emotion/styled'; -import { ClearButton, ClearUl } from '@/components'; +// import { ClearButton, ClearUl } from '@/components'; -export const CommentsBox = styled(ClearUl)` - margin-top: 10px; - padding: 5px -0; - border-top: 1px solid #f5f5f5; -`; +// export const CommentsBox = styled(ClearUl)` +// margin-top: 10px; +// padding: 5px -0; +// border-top: 1px solid #f5f5f5; +// `; -export const BackLink = styled(ClearButton)` - padding: 5px 4px; - font-size: 11px; - line-height: 13px; -`; +// export const BackLink = styled(ClearButton)` +// padding: 5px 4px; +// font-size: 11px; +// line-height: 13px; +// `; -export const Li = styled.li` - padding: 0 0 5px 15px; -`; +// export const Li = styled.li` +// padding: 0 0 5px 15px; +// `; diff --git a/src/pages/board/postDetail/components/index.ts b/src/pages/board/postDetail/components/index.ts index d26e0544..20b44842 100644 --- a/src/pages/board/postDetail/components/index.ts +++ b/src/pages/board/postDetail/components/index.ts @@ -1,4 +1,4 @@ -export { PostReplyComments } from './ReplyComment'; +// export { PostReplyComments } from './ReplyComment'; export { PostComments } from './Comment'; export { CommentInput } from './CommentInput'; export { CommentMenu } from './CommentMenu'; diff --git a/yarn.lock b/yarn.lock index fa0e9f32..3c403706 100644 --- a/yarn.lock +++ b/yarn.lock @@ -367,10 +367,10 @@ resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz" integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww== -"@esbuild/win32-x64@0.19.11": +"@esbuild/darwin-arm64@0.19.11": version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz" - integrity sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw== + resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.11.tgz" + integrity sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ== "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" @@ -681,10 +681,10 @@ estree-walker "^2.0.2" picomatch "^2.3.1" -"@rollup/rollup-win32-x64-msvc@4.9.4": +"@rollup/rollup-darwin-arm64@4.9.4": version "4.9.4" - resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.4.tgz" - integrity sha512-LfdGXCV9rdEify1oxlN9eamvDSjv9md9ZVMAbNHA87xqIfFCxImxan9qZ8+Un54iK2nnqPlbnSi4R54ONtbWBw== + resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.4.tgz" + integrity sha512-1fzh1lWExwSTWy8vJPnNbNM02WZDS8AW3McEOb7wW+nPChLKf3WG2aG7fhaUmfX5FKw9zhsF5+MBwArGyNM7NA== "@svgr/babel-plugin-add-jsx-attribute@8.0.0": version "8.0.0" @@ -2298,6 +2298,16 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +fsevents@2.3.2: + version "2.3.2" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"