const InfinityArticleLists = ({ setExpandedIndexes, setExpandedTagsIndexes, expandedIndexes, expandedTagsIndexes }: Props) => {
const pageSize = 20
const {
data: InfinityArticles,
fetchNextPage,
hasNextPage,
isLoading,
} = useInfiniteQuery({
//'all'은 추후에 수정 -> selectedDate란 내가 보기옵션에서 고른 날짜값 이건 무한 스크롤과 별개로
//리액트 쿼리문은 쿼리키의 값에따라 고유한 데이터를 갖는데 만약 쿼리키가 같다면
//해당데이터를 다르다고 인식하지 못해 내가 원하는대로 동작 구현이 안됨.
queryKey: ['keys'],
queryFn: ({ pageParam }) =>
//getNextPageParam에 따라 값이 바뀌는 pageParam
service.getLlompsStockRelatedPost({
result: {
companyName: 'xxxx',
startDate: '2024-12-01',
endDate: '2025-02-11',
pageNumber: pageParam,
pageSize
}
}),
initialPageParam: 1,
select: (data) => {
return data;
},
getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) => {
if (lastPage.pageNumber === lastPage.pages) {
//no next page available
return undefined;
}
return lastPage.pageNumber + 1;
},
})
const postList = InfinityArticles?.pages[0]
const rowRenderer: ListProps['rowRenderer'] = ({ index, key, parent, style }) => {
const post = InfinityArticles?.pages.flatMap(page => page.items)[index]; // ✅ 올바르게 한 개의 post만 가져오기
// console.log('post:', post)
if (!post) return null; // 데이터가 없으면 아무것도 렌더링하지 않음
return (
<CellMeasurer cache={cache} parent={parent} key={key} columnIndex={0} rowIndex={index}>
{({ registerChild }) => (
<div ref={registerChild as any} style={style}>
<div>
<InfinityArticleFrame key={index} expandedIndexes={expandedIndexes} toggleNews={toggleNews} index={index} item={post} />
</div>
</div>
)}
</CellMeasurer>
)
}
if (isLoading) return <div>loading...</div>
return (
<WindowScroller>
{({ height, scrollTop, isScrolling, onChildScroll, registerChild }) => (
<div ref={registerChild as any} css={{}}>
<AutoSizer disableHeight>
{({ width }) => (
<List
ref={handleList}
autoHeight
height={height}
width={width}
isScrolling={isScrolling}
overscanRowCount={0}
onScroll={onChildScroll}
scrollTop={scrollTop}
// rowCount={postList?.total ?? 0}
rowCount={InfinityArticles?.pages.reduce((acc, page) => acc + page.items.length, 0) ?? 0}
rowHeight={cache.rowHeight}
rowRenderer={rowRenderer}
defferedMeasurementCache={cache}
//! Hydration 경고 해제용 See: https://github.com/bvaughn/react-virtualized/issues/1737#issuecomment-1219820104
style={{ overflowY: 'auto' }}
/>
)}
</AutoSizer>
</div>
)}
</WindowScroller>
)
}
export default InfinityArticleLists;
lastPage에는 마지막 페이지에 대한 정보와 백에서 보내준 date가 담겨있다 이것들을 적절하게 이용하면 다음 페이지에 대한 값을 줄수 있고 또한 마지막 페이지에 도달했다면 undefined를 return하여 nextPage가 없다는 걸 암시할수도 있다.
각 행에 대한 css 처리 및 렌더링 구현이라고 보면 된다. 처음에 제대로 이해를 못하고 여기서 data를 전부 map 돌려서 데이터가 무수히 계속 나오는 신세계를 경험했다...
약간의 로직을 추가해서 DateSeparator를 여기서 적용했다.
{!isDuplicateDate && <DateSeparator date={post.pubDate} />}
rowCount란 각 페이지마다의 item.length을 더해 총 row 개수를 계산.
rowCount={InfinityArticles?.pages.reduce((acc, page) => acc + page.items?.length, 0) ?? 0}
-> List는 rowCount 만큼 가상 공간을 확보하고 필요할때만 row 렌더링.
현재 가장 골치아픈 녀석이다. 25.02.18

동적 높이는 허용했지만 이렇게까지 차이가 나는 이유를 모르겠다.
400이상으로 height 나올 이유가 없는데 350~500 너무 폭차가 크다. 분명 이유가 있을텐데...
원래 rowRenderer에서 코드가 CellMeasurer 에서 return을 이렇게 던졌는데 이때 DateSeparator의 크기가 제대로 rowHeight에 반영되지 않는 느낌이었다. 렌더링할때 정확하게 높이를 추가해서 주는게 아니라 때에 따라 계속해서 다르게 주는듯한...? 그래서 일단 InfinityArticleFrame 안에서 추가해주도록 했음 (크게 의미는 없었지만 최대한 변수를 없애고자 했다 ㅎㅎ)
return (
<div>
<DateSeparator />
<InfinityArticleFrame key={post.id} />
</div>
)
두번째 500넘게 나오는 수치가 정확히 보니 뉴스더보기 버튼이 있는데 이 버튼을 클릭하면 최대치가 그정도 잡히게 된다. 뉴스더보기 버튼을 렌더링하는 조건은 안에 있는데 아마 이부분이 계산이 잘 안되어? (추측 : 잘된 row도 있고 그렇지 않은 row도 있었기에) 따라서 변수를 모조리 없애버리기 위해 뉴스더보기 버튼과 DateSeparator에 있던 margin 과 padding은 과감히 없애고 rowRenderer 에 바로 영향을 받는 InfinityArticleFrame에서만 margin과 padding을 적용하도록 했다.