diff --git a/src/components/epigram/Comment/CommentList.tsx b/src/components/epigram/Comment/CommentList.tsx
index 5a605fe9..9d06bd9c 100644
--- a/src/components/epigram/Comment/CommentList.tsx
+++ b/src/components/epigram/Comment/CommentList.tsx
@@ -1,27 +1,66 @@
-import useEpigramCommentsQuery from '@/hooks/useEpigramCommentHook';
+import React, { useEffect, useRef, useCallback } from 'react';
import { EpigramCommentProps } from '@/types/epigram.types';
+import useEpigramCommentsQuery from '@/hooks/useEpigramCommentsQueryHook';
import CommentItem from './CommentItem';
import NoComment from './NoComment';
function CommentList({ epigramId, currentUserId }: EpigramCommentProps) {
- const {
- data: comments,
- isLoading,
- error,
- } = useEpigramCommentsQuery({
- id: epigramId,
- limit: 3,
- });
-
- if (isLoading) return
댓글을 불러오는 중...
;
- if (error) return 에러: {(error as Error).message}
;
- const commentCount = comments?.list.length || 0;
+ const { data, fetchNextPage, hasNextPage, isFetchingNextPage, status } = useEpigramCommentsQuery(epigramId);
+
+ const observerRef = useRef(null);
+ const lastCommentRef = useRef(null);
+
+ const handleObserver = useCallback(
+ (entries: IntersectionObserverEntry[]) => {
+ const [target] = entries;
+ if (target.isIntersecting && hasNextPage) {
+ fetchNextPage();
+ }
+ },
+ [fetchNextPage, hasNextPage],
+ );
+
+ useEffect(() => {
+ const options = {
+ root: null,
+ rootMargin: '20px',
+ threshold: 1.0,
+ };
+
+ observerRef.current = new IntersectionObserver(handleObserver, options);
+
+ if (lastCommentRef.current) {
+ observerRef.current.observe(lastCommentRef.current);
+ }
+
+ return () => {
+ if (observerRef.current) {
+ observerRef.current.disconnect();
+ }
+ };
+ }, [handleObserver]);
+
+ if (status === 'pending') return 댓글을 불러오는 중...
;
+ if (status === 'error') return 에러: 댓글을 불러오는데 실패했습니다.
;
+
+ const allComments = data?.pages.flatMap((page) => page.list) || [];
+ const totalCount = data?.pages[0]?.totalCount || 0;
return (
-
댓글({comments?.totalCount})
- {commentCount > 0 ? comments?.list.map((comment) =>
) :
}
+
댓글({totalCount})
+ {allComments.length > 0 ? (
+ <>
+ {allComments.map((comment) => (
+
+ ))}
+
{isFetchingNextPage &&
더 많은 댓글을 불러오는 중...
}
+ >
+ ) : (
+
+ )}
);
}
+
export default CommentList;
diff --git a/src/hooks/useEpigramCommentHook.ts b/src/hooks/useEpigramCommentHook.ts
deleted file mode 100644
index 126695f5..00000000
--- a/src/hooks/useEpigramCommentHook.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import queries from '@/apis/queries';
-import { CommentRequestType } from '@/schema/comment';
-import { useQuery } from '@tanstack/react-query';
-
-const useEpigramCommentsQuery = (request: CommentRequestType) => useQuery(queries.epigramComment.getComments(request));
-
-export default useEpigramCommentsQuery;
diff --git a/src/hooks/useEpigramCommentsQueryHook.ts b/src/hooks/useEpigramCommentsQueryHook.ts
new file mode 100644
index 00000000..9c7a34a5
--- /dev/null
+++ b/src/hooks/useEpigramCommentsQueryHook.ts
@@ -0,0 +1,13 @@
+import { InfiniteData, useInfiniteQuery } from '@tanstack/react-query';
+import { CommentResponseType } from '@/schema/comment';
+import getEpigramComments from '@/apis/epigramComment';
+
+const useEpigramCommentsQuery = (epigramId: number) =>
+ useInfiniteQuery, [string, number], number | undefined>({
+ queryKey: ['epigramComments', epigramId],
+ queryFn: ({ pageParam }) => getEpigramComments({ id: epigramId, limit: 3, cursor: pageParam }),
+ initialPageParam: undefined,
+ getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,
+ });
+
+export default useEpigramCommentsQuery;
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
index 076364a3..737859ce 100644
--- a/src/lib/constants.ts
+++ b/src/lib/constants.ts
@@ -1,4 +1,4 @@
const TOKEN =
- 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MjIsInRlYW1JZCI6IjUtOSIsInNjb3BlIjoiYWNjZXNzIiwiaWF0IjoxNzIxMTg3NDgyLCJleHAiOjE3MjExODkyODIsImlzcyI6InNwLWVwaWdyYW0ifQ.Qpw2ByeGF-rkQ1wwJ2c7OtjyVXBevOsZhMeyuzZjosM';
+ 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MjIsInRlYW1JZCI6IjUtOSIsInNjb3BlIjoiYWNjZXNzIiwiaWF0IjoxNzIxMjAwMTI0LCJleHAiOjE3MjEyMDE5MjQsImlzcyI6InNwLWVwaWdyYW0ifQ.BUQ4EAR04HMIg5YMAJI8Rd7aa6_GyAoZs89YL0TuCgg';
export default TOKEN;