11import { MasonryInfiniteGrid } from '@egjs/react-infinitegrid' ;
2- import { useMutation , useQuery , useQueryClient } from '@tanstack/react-query' ;
3- import { useState } from 'react' ;
2+ import { useMutation , useInfiniteQuery , useQueryClient } from '@tanstack/react-query' ;
3+ import { useState , useCallback } from 'react' ;
44import { useParams } from 'react-router' ;
55
66import { deleteRollingPaperComment , getRollingPaperDetail } from '@/apis/rolling' ;
@@ -14,6 +14,8 @@ import CommentDetailModal from './components/CommentDetailModal';
1414import WriteCommentButton from './components/WriteCommentButton' ;
1515import useAuthStore from '@/stores/authStore' ;
1616
17+ const MESSAGE_SIZE = 10 ;
18+
1719const RollingPaperPage = ( ) => {
1820 const id = useParams ( ) . id ?? '' ;
1921 const [ activeComment , setActiveComment ] = useState < RollingPaperComment | null > ( null ) ;
@@ -22,35 +24,36 @@ const RollingPaperPage = () => {
2224 const zipCode = useAuthStore ( ( props ) => props . zipCode ) ;
2325 const queryClient = useQueryClient ( ) ;
2426
25- const { data, isSuccess } = useQuery ( {
27+ const { data, isSuccess, fetchNextPage , hasNextPage , isFetchingNextPage } = useInfiniteQuery ( {
2628 queryKey : [ 'rolling-paper' , id ] ,
27- queryFn : ( ) => getRollingPaperDetail ( id ) ,
29+ queryFn : ( { pageParam = 1 } ) => getRollingPaperDetail ( id , pageParam , MESSAGE_SIZE ) ,
30+ getNextPageParam : ( lastPage ) => {
31+ const { currentPage, totalPages } = lastPage . eventPostComments ;
32+ return currentPage < totalPages ? currentPage + 1 : undefined ;
33+ } ,
34+ initialPageParam : 1 ,
2835 } ) ;
2936
3037 const { mutate : deleteComment } = useMutation ( {
3138 mutationFn : ( rollingPaperId : number | string ) => deleteRollingPaperComment ( rollingPaperId ) ,
32- onSuccess : ( data ) => {
33- queryClient . setQueryData ( [ 'rolling-paper' , id ] , ( oldData : RollingPaper ) => {
34- if ( ! oldData ) return oldData ;
35-
36- return {
37- ...oldData ,
38- eventPostComments : {
39- content : oldData . eventPostComments . content . filter (
40- ( comment : RollingPaperComment ) => comment . commentId !== data . commentId ,
41- ) ,
42- } ,
43- } ;
44- } ) ;
45-
39+ onSuccess : ( ) => {
40+ queryClient . invalidateQueries ( { queryKey : [ 'rolling-paper' , id ] } ) ;
4641 setActiveDeleteModal ( false ) ;
4742 setActiveComment ( null ) ;
4843 } ,
49- onError : ( err ) => {
50- console . error ( err ) ;
44+ onError : ( ) => {
45+ alert ( '편지 삭제에 실패했어요. 다시 시도해주세요' ) ;
5146 } ,
5247 } ) ;
5348
49+ const handleLoadMore = useCallback ( ( ) => {
50+ if ( ! isFetchingNextPage && hasNextPage ) fetchNextPage ( ) ;
51+ } , [ fetchNextPage , hasNextPage , isFetchingNextPage ] ) ;
52+
53+ const allComments = data ?. pages . flatMap ( ( page ) => page . eventPostComments . content ) || [ ] ;
54+ const totalComments = data ?. pages [ 0 ] ?. eventPostComments . totalElements || 0 ;
55+ const title = data ?. pages [ 0 ] ?. title || '' ;
56+
5457 return (
5558 < >
5659 { activeDetailModal && activeComment && (
@@ -84,14 +87,12 @@ const RollingPaperPage = () => {
8487 ) }
8588 < Header />
8689 < main className = "flex grow flex-col items-center px-5 pt-20 pb-12" >
87- < PageTitle className = "mb-18 max-w-73 text-center" > { data ?. title } </ PageTitle >
88- < p className = "body-sb text-gray-60 mb-2 w-full" >
89- 등록된 편지 { data ? data . eventPostComments . content . length : 0 }
90- </ p >
90+ < PageTitle className = "mb-18 max-w-73 text-center" > { title } </ PageTitle >
91+ < p className = "body-sb text-gray-60 mb-2 w-full" > 등록된 편지 { totalComments } </ p >
9192 < section className = "w-full" >
92- < MasonryInfiniteGrid column = { 2 } align = "stretch" gap = { 16 } >
93+ < MasonryInfiniteGrid column = { 2 } align = "stretch" gap = { 16 } onRequestAppend = { handleLoadMore } >
9394 { isSuccess &&
94- data . eventPostComments . content . map ( ( comment ) => (
95+ allComments . map ( ( comment ) => (
9596 < Comment
9697 key = { comment . commentId }
9798 comment = { comment }
@@ -102,13 +103,16 @@ const RollingPaperPage = () => {
102103 />
103104 ) ) }
104105 </ MasonryInfiniteGrid >
105- { isSuccess && data . eventPostComments . content . length === 0 && (
106+ { isSuccess && allComments . length === 0 && (
106107 < p className = "body-sb text-gray-60 my-20 text-center" >
107108 아직 등록된 편지가 없어요.
108109 < br />
109110 첫번째로 편지를 남겨볼까요?
110111 </ p >
111112 ) }
113+ { isFetchingNextPage && (
114+ < p className = "body-sb text-gray-60 my-4 text-center" > Loading...</ p >
115+ ) }
112116 </ section >
113117 < WriteCommentButton rollingPaperId = { id } />
114118 </ main >
0 commit comments