feat: 가상 스크롤 동적 높이 지원
- measureElement와 data-index 사용으로 각 아이템 실제 높이 측정 - 고정 높이(h-[120px]) 제거하여 내용에 맞게 자동 조절
This commit is contained in:
parent
0cab67dfbe
commit
d22466ec23
1 changed files with 7 additions and 6 deletions
|
|
@ -43,7 +43,7 @@ function Schedule() {
|
||||||
const [searchInput, setSearchInput] = useState('');
|
const [searchInput, setSearchInput] = useState('');
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
const SEARCH_LIMIT = 20; // 페이지당 20개
|
const SEARCH_LIMIT = 20; // 페이지당 20개
|
||||||
const ITEM_HEIGHT = 136; // 각 아이템 높이 (120px) + 간격 (16px)
|
const ESTIMATED_ITEM_HEIGHT = 120; // 아이템 추정 높이 (동적 측정)
|
||||||
|
|
||||||
// Intersection Observer for infinite scroll
|
// Intersection Observer for infinite scroll
|
||||||
const { ref: loadMoreRef, inView } = useInView({
|
const { ref: loadMoreRef, inView } = useInView({
|
||||||
|
|
@ -289,11 +289,11 @@ function Schedule() {
|
||||||
});
|
});
|
||||||
}, [schedules, selectedDate, currentYearMonth, selectedCategories, isSearchMode, searchTerm, searchResults]);
|
}, [schedules, selectedDate, currentYearMonth, selectedCategories, isSearchMode, searchTerm, searchResults]);
|
||||||
|
|
||||||
// 가상 스크롤 설정 (검색 모드에서만 활성화)
|
// 가상 스크롤 설정 (검색 모드에서만 활성화, 동적 높이 지원)
|
||||||
const virtualizer = useVirtualizer({
|
const virtualizer = useVirtualizer({
|
||||||
count: isSearchMode && searchTerm ? filteredSchedules.length : 0,
|
count: isSearchMode && searchTerm ? filteredSchedules.length : 0,
|
||||||
getScrollElement: () => scrollContainerRef.current,
|
getScrollElement: () => scrollContainerRef.current,
|
||||||
estimateSize: () => ITEM_HEIGHT,
|
estimateSize: () => ESTIMATED_ITEM_HEIGHT,
|
||||||
overscan: 5, // 버퍼 아이템 수
|
overscan: 5, // 버퍼 아이템 수
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -834,7 +834,7 @@ function Schedule() {
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
height: `${virtualizer.getTotalSize() - 16}px`,
|
height: `${virtualizer.getTotalSize()}px`,
|
||||||
width: '100%',
|
width: '100%',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
}}
|
}}
|
||||||
|
|
@ -850,19 +850,20 @@ function Schedule() {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={virtualItem.key}
|
key={virtualItem.key}
|
||||||
|
ref={virtualizer.measureElement}
|
||||||
|
data-index={virtualItem.index}
|
||||||
style={{
|
style={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: 0,
|
top: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: `${virtualItem.size}px`,
|
|
||||||
transform: `translateY(${virtualItem.start}px)`,
|
transform: `translateY(${virtualItem.start}px)`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className={virtualItem.index < filteredSchedules.length - 1 ? "pb-4" : ""}>
|
<div className={virtualItem.index < filteredSchedules.length - 1 ? "pb-4" : ""}>
|
||||||
<div
|
<div
|
||||||
onClick={() => handleScheduleClick(schedule)}
|
onClick={() => handleScheduleClick(schedule)}
|
||||||
className="flex items-stretch bg-white rounded-2xl shadow-sm hover:shadow-md transition-shadow overflow-hidden cursor-pointer h-[120px]"
|
className="flex items-stretch bg-white rounded-2xl shadow-sm hover:shadow-md transition-shadow overflow-hidden cursor-pointer"
|
||||||
>
|
>
|
||||||
{/* 날짜 영역 */}
|
{/* 날짜 영역 */}
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue