Skip to content

Commit

Permalink
feat: reply comment UI 추가 - flickering 오류 고치기 (#112)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ontheway-01 committed Mar 27, 2024
1 parent 67cd074 commit 8a56d59
Show file tree
Hide file tree
Showing 12 changed files with 250 additions and 130 deletions.
6 changes: 3 additions & 3 deletions src/pages/board/postDetail/PostDetailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
PostAuthor,
PostComments,
PostDetailMenu,
PostReplyComments,
// PostReplyComments,
} from './components';
import { CommentDeleteModal } from './components/CommentDeleteModal';
import { PostDeleteModal } from './components/PostDeleteModal';
Expand Down Expand Up @@ -61,7 +61,7 @@ const PostDetailPage: React.FC = observer(() => {
</div>
<PostCommentNum>{post.commentCount}</PostCommentNum>
<Switch>
<Route path={PAGE_URL.PostReplyComment} component={PostReplyComments} />
{/* <Route path={PAGE_URL.PostReplyComment} component={PostReplyComments} /> */}
<Route path={PAGE_URL.PostDetail} component={PostComments} />
</Switch>
</BodyScreen>
Expand All @@ -72,7 +72,7 @@ const PostDetailPage: React.FC = observer(() => {
<>{/* TODO: 페이지 스켈레톤 */}</>
)}
<PostDeleteModal />
<CommentMenu />
{/* <CommentMenu /> */}
<CommentDeleteModal />
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -43,23 +44,19 @@ export const CommentCardContainer: React.FC<Props> = 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 (
<li ref={ref} {...bind()}>
<CommentCardView state={commentState} model={model} />
{withReplyLink && model.numChildComment ? (
<ReplyLink onClick={handleGoReply(params, model)}>
답글 {model.numChildComment}개 더보기
</ReplyLink>
) : null}
{model.numChildComment != 0 ? <PostReplyComments model={model} /> : null}
</li>
);
},
Expand Down
Original file line number Diff line number Diff line change
@@ -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<PostParams>();
//const { replace } = useHistory();
const {
setVirtuosoRef,
screenRef,
replyComments: { fetch, reset, parent, comments, hasMore, page },
commentInput: { resetState },
} = usePageUiStore<PageUiStore.PostDetail>();

// const handleBack = useCallback(
// () => replace(generatePath(PAGE_URL.PostDetail, { boardId, postId })),
// [boardId, postId],
// );

const virtuoso = useRef(null);
const timer = useRef<NodeJS.Timeout>();
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 ? (
<ReplyCommentsBox>
<Virtuoso
ref={virtuoso}
style={{ maxHeight: '100vh', marginTop: '5px' }}
customScrollParent={screenRef?.current as HTMLElement}
endReached={loadMore(hasMore, page)}
overscan={200}
data={comments}
itemContent={(index, comment) => <ReplyCommentContainer key={comment.id} model={comment} />}
/>
</ReplyCommentsBox>
) : null;
});
Original file line number Diff line number Diff line change
@@ -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<HTMLLIElement>(null);
const {
commentInput,
commentMenuModal: { open },
} = usePageUiStore<PageUiStore.PostDetail>();
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 (
<Li ref={ref} {...bind()}>
<CommentCardView state={state} model={model} />
</Li>
);
});
16 changes: 16 additions & 0 deletions src/pages/board/postDetail/components/Comment/styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
`;
Original file line number Diff line number Diff line change
Expand Up @@ -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<PostParams>();
const {
ui: { alert },
Expand Down Expand Up @@ -76,11 +77,9 @@ export const CommentInputContainer: React.FC = observer(() => {
return (
<FormProvider {...methods}>
<Nav>
<ReplyChip />
<EditChip />
<CommentInputView
onSubmit={methods.handleSubmit(handleSubmit(isReplyComment, virtuosoRef))}
/>
{/* <ReplyChip />
<EditChip /> */}
<CommentInputView onSubmit={methods.handleSubmit(handleSubmit(false, virtuosoRef))} />
</Nav>
</FormProvider>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -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<PostParams>();
const { replace } = useHistory();
const {
setVirtuosoRef,
screenRef,
replyComments: { fetch, reset, parent, comments, hasMore, page },
commentInput: { resetState },
} = usePageUiStore<PageUiStore.PostDetail>();
// export const PostReplyComments: React.FC = observer(() => {
// const { boardId, postId, commentId } = useParams<PostParams>();
// const { replace } = useHistory();
// const {
// setVirtuosoRef,
// screenRef,
// replyComments: { fetch, reset, parent, comments, hasMore, page },
// commentInput: { resetState },
// } = usePageUiStore<PageUiStore.PostDetail>();

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<NodeJS.Timeout>();
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<NodeJS.Timeout>();
// 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 ? (
<CommentsBox>
<BackLink onClick={handleBack}>전체 댓글로 이동하기</BackLink>
<CommentCard model={parent} />
<Virtuoso
ref={virtuoso}
style={{ maxHeight: '100vh', marginTop: '5px' }}
customScrollParent={screenRef?.current as HTMLElement}
endReached={loadMore(hasMore, page)}
overscan={200}
data={comments}
itemContent={(index, comment) => <ReplyCommentContainer key={comment.id} model={comment} />}
/>
</CommentsBox>
) : null;
});
// return parent ? (
// <CommentsBox>
// <BackLink onClick={handleBack}>전체 댓글로 이동하기</BackLink>
// <CommentCard model={parent} />
// <Virtuoso
// ref={virtuoso}
// style={{ maxHeight: '100vh', marginTop: '5px' }}
// customScrollParent={screenRef?.current as HTMLElement}
// endReached={loadMore(hasMore, page)}
// overscan={200}
// data={comments}
// itemContent={(index, comment) => <ReplyCommentContainer key={comment.id} model={comment} />}
// />
// </CommentsBox>
// ) : null;
// });
Original file line number Diff line number Diff line change
@@ -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<HTMLLIElement>(null);
const {
commentInput,
commentMenuModal: { open },
} = usePageUiStore<PageUiStore.PostDetail>();
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<HTMLLIElement>(null);
// const {
// commentInput,
// commentMenuModal: { open },
// } = usePageUiStore<PageUiStore.PostDetail>();
// 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 (
<Li ref={ref} {...bind()}>
<CommentCardView state={state} model={model} />
</Li>
);
});
// return (
// <Li ref={ref} {...bind()}>
// <CommentCardView state={state} model={model} />
// </Li>
// );
// });
Loading

0 comments on commit 8a56d59

Please sign in to comment.