Infinite scroll and virtualization lag
維護者通常 1 天內回覆
還沒有人認領這個 Issue。
評估
- 難度
- 4/5
- 預估耗時
- 3-5 天
- 新手友好度
- 35/100
- Issue 類型
- 缺陷
- 描述清晰度
- 需要釐清
- 活躍度
- 停滯
- 技術堆疊
- react, typescript
- 領域
- frontend, performance
研究方向
從提供的 CandidatesListTable 和 DataTable 程式碼開始,重點關注 @tanstack/react-virtual 的設定、tableContainerRef 以及 ScrollArea 的 handleScroll 路徑。在捲動時重現 infinite-scroll API 呼叫,然後確認捲動元素和虛擬化行為是否與範例一致。頁面擷取期間能夠順暢捲動且虛擬化正常運作,即表示完成。
由索引模型根據 Issue 內容生成。
描述
Describe the bug
Iam using Shadcn ui tables which is built on top of the tanstack tables,
i need a infinite scroll which should be smooth -initially it was smooth (befor infinite scroll) until i add infinite scroll for pagination, there it is getting lag
at the time of the calling for the next page it is getting lag
and in case of virtualization- i didn't get why it is not virtualized i followed everything according to the examples given
it would be really help full if any one help me fix this.
`import React from "react";
import { useDispatch, useSelector } from "react-redux";
import Columns from "./Columns";
import DataTable from "../tables/DataTable";
import { useEffect } from "react";
import {
fetchCandidates,
getCandidates,
} from "../../features/candidates/candidateThunks";
import { useState } from "react";
import {
QueryClient,
QueryClientProvider,
keepPreviousData,
useInfiniteQuery,
} from "@tanstack/react-query";
import { extractValueFromUrl } from "../../features/common/staticUtils";
function CandidatesListTable() {
// useGetCandidates();
// const data = useSelector((state) => state.candidates.data);
const dispatch = useDispatch();
const { data, fetchNextPage, hasNextPage, isFetching, isLoading } =
useInfiniteQuery({
queryKey: [
"candidates",
// sorting, //refetch when sorting changes
],
queryFn: async ({pageParam=1}) => {
const fetchedData = await fetchCandidates({pageParam});
return fetchedData;
},
initialPageParam: 1,
getNextPageParam: (lastPage, pages) => {
const nextPage = extractValueFromUrl(lastPage.next, "page");
const next=Number(nextPage)
console.log(nextPage, "next page infy");
return next?next:undefined
},
refetchOnWindowFocus: false,
placeholderData: keepPreviousData,
});
// console.log(
// data,
// fetchNextPage,
// hasNextPage,
// isFetching,
// isLoading,
// "check for the infy"
// );
return (
<>
</>
);
}
export default CandidatesListTable;
import {
flexRender,
getCoreRowModel,
getFilteredRowModel,
useReactTable
} from "@tanstack/react-table";
import { useEffect } from "react";
import { ScrollArea } from "../ui/scroll-area.jsx";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "../ui/table.jsx";
import { useVirtualizer } from "@tanstack/react-virtual";
import { useCallback, useMemo, useRef, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import useDebounce from "../../hooks/useDebounce.js";
import { cn } from "../../lib/utils.js";
import ViewSideBar from "../virtualTables/ViewSideBar.js";
import DataTableControlsAndFilters from "./DataTableControlsAndFilters.js";
function DataTable({ data, fetchNextPage, isFetching, isLoading, columns }) {
const dispatch = useDispatch();
const tableContainerRef = useRef(null);
const totalCount = data?.totalCount;
const isSiderOpen = useSelector((state) => state.virtualTables.isSiderOpen);
const debouncedIsHovered = useDebounce(isSiderOpen, 500);
const [open, setOpen] = useState(false);
const [container, setContainer] = useState(null);
//flatten the array of arrays from the useInfiniteQuery hook
const flatData = useMemo(
() => data?.pages?.flatMap((page) => page.results) ?? [],
[data]
);
useEffect(() => {
console.log(flatData, "flatdata");
}, [flatData]);
const totalDBRowCount = data?.pages?.[0]?.count ?? 0;
const totalFetched = flatData.length;
//called on scroll and possibly on mount to fetch more data as the user scrolls and reaches bottom of table
const fetchMoreOnBottomReached = useCallback(
(containerRefElement) => {
if (containerRefElement) {
const { scrollHeight, scrollTop, clientHeight } = containerRefElement;
//once the user has scrolled within 500px of the bottom of the table, fetch more data if we can
if (
scrollHeight - scrollTop - clientHeight < 1500 &&
!isFetching &&
totalFetched < totalDBRowCount
) {
console.log(
scrollHeight - scrollTop - clientHeight,
"check for the iop"
);
fetchNextPage();
}
}
},
[fetchNextPage, isFetching, totalFetched, totalDBRowCount]
);
useEffect(() => {
fetchMoreOnBottomReached(tableContainerRef.current);
}, []);
const table = useReactTable({
data: flatData,
columns,
// manualPagination: true,
// onSortingChange: setSorting,
// onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
// getPaginationRowModel: getPaginationRowModel(),
// getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
// manualSorting: true,
debugTable: true,
// onPaginationChange:(e)=>{
// console.log("onPaginationChange",e())
// }
// onColumnVisibilityChange: setColumnVisibility,
// // onRowSelectionChange: setRowSelection,
// state: {
// sorting,
// columnFilters,
// columnVisibility,
// rowSelection,
// },
});
const { rows } = table.getRowModel();
const virtualizer = useVirtualizer({
count: rows.length,
estimateSize: () => 33, //estimate row height for accurate scrollbar dragging
getScrollElement: () => tableContainerRef.current,
//measure dynamic row height, except in firefox because it measures table border height incorrectly
measureElement:
typeof window !== "undefined" &&
navigator.userAgent.indexOf("Firefox") === -1
? (element) => element?.getBoundingClientRect().height
: undefined,
overscan: 5,
});
console.log(virtualizer.getVirtualItems().length,'length')
return (
<div
className={cn(" h-[calc(100vh_-158px)] relative w-full flex flex-row")}
>
{" "}
{open && <ViewSideBar />}
<ScrollArea
handleScroll={fetchMoreOnBottomReached}
// ref={tableContainerRef}
className={cn(
`relative overflow-auto`,
`w-full`
// `h-[${virtualizer.getTotalSize()}px]`
)}
>
<div className="h-full w-full" ref={tableContainerRef}>
<Table style={{ display: "grid" }} className="h-full">
<TableHeader
style={{
display: "grid",
position: "sticky",
top: 0,
zIndex: 1,
}}
className="sticky top-0 bg-white z-10"
>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow
style={{ display: "flex", width: "100%" }}
key={headerGroup.id}
>
{headerGroup.headers.map((header) => {
return (
<TableHead
style={{
display: "flex",
width: header.getSize(),
}}
key={header.id}
>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody
style={{
display: "grid",
height: `${virtualizer.getTotalSize()}px`, //tells scrollbar how big the table is
position: "relative", //needed for absolute positioning of rows
}}
onScroll={(e) => console.log(e, "scrolllingf")}
>
{virtualizer.getVirtualItems()?.length > 0 ? (
<>
{virtualizer.getVirtualItems()?.map((virtualRow, index) => {
const row = rows[virtualRow.index];
const loader = virtualRow.index > rows?.length - 1;
return (
<TableRow
data-index={virtualRow.index} //needed for dynamic row height measurement
ref={(node) => virtualizer.measureElement(node)} //measure dynamic row height
key={row.id}
style={{
display: "flex",
position: "absolute",
transform: `translateY(${virtualRow.start}px)`, //this should always be a `style` as it changes on scroll
width: "100%",
}}
// key={row?.id}
// style={{
// // height: `${virtualRow.size}px`,
// transform: `translateY(${
// virtualRow.start - index * virtualRow.size
// }px)`,
// }}
data-state={row?.getIsSelected() && "selected"}
>
{row?.getVisibleCells().map((cell) => (
<TableCell
key={cell.id}
style={{
display: "flex",
width: cell.column.getSize(),
}}
>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
);
})}
{/* <Loader2
ref={ref}
className="react-table my-4 h-8 w-8 animate-spin"
/> */}
</>
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
</ScrollArea>
</div>
{/* <DataTableFooter table={table} /> */}
</div>
);
}
export default DataTable;
`
thank you
Your minimal, reproducible example
vs code
Steps to reproduce
in infinite scroll at the time of api call there has been a lag
Expected behavior
the scroll should be smooth
How often does this bug happen?
None
Screenshots or Videos
No response
Platform
linux
tanstack-virtual version
v3.5.0
TypeScript version
No response
Additional context
No response
Terms & Code of Conduct
- I agree to follow this project's Code of Conduct
- I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.
- 主要語言
- TypeScript
- 星號
- 7.2k
- 分支
- 484
- 平均合併
- 16 小時 14 分鐘
- 30 天內合併 PR
- 45
環境準備
- 沒有 Dockerfile 或 Docker Compose 檔案
- 有 Pull Request 範本
- 閱讀貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
TanStack/virtual 的其他 Issue
-
anchorTo: 'end' loses the end when the scroll element shrinks可能已有人在做 @langleyd 於 26 天前認領。 未關閉
難度 3/5 1-2 天 新手友好度 68/100
維護者通常 1 天內回覆
-
marko-virtual: scrollToEnd during an in-flight prepend strands the view one prepend above the bottom (chat-pretext e2e fails on CI)可能已有人在做 @prayaggaikwad96 於 20 天前認領。 未關閉
難度 4/5 3-5 天 新手友好度 55/100
維護者通常 1 天內回覆
-
難度 4/5 3-5 天 新手友好度 42/100
TanStack/virtual#1252 · 2 則留言 ·
維護者通常 1 天內回覆
-
eslint-plugin-react-hooks v7 warning for useVirtualizer: Compilation Skipped: Use of incompatible library可能已有人在做 關聯的 PR 仍在進行中或已合併。 未關閉
難度 4/5 3-5 天 新手友好度 45/100
TanStack/virtual#1119 · 11 則留言 · 32 個 reaction ·
維護者通常 1 天內回覆
-
難度 4/5 3-5 天 新手友好度 35/100
TanStack/virtual#1099 · 1 個 reaction ·
維護者通常 1 天內回覆
相似的 Issue
-
難度 2/5 1-3 小時 新手友好度 72/100
維護者通常 1 天內回覆
-
ready-for-agent
難度 2/5 1-3 小時 新手友好度 72/100
LucasSantana-Dev/Lucky#2951 ·
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 75/100
danielmiessler/LifeOS#2567 ·
維護者通常 9 天內回覆
-
refactor(react-pi): classify base64 images with core's parseBase64可能已有人在做 @jimmyallinai 今天認領。 未關閉maintenance
難度 2/5 1-3 小時 新手友好度 62/100
assistant-ui/assistant-ui#10293 · 2 則留言 · 1 個 reaction ·
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 70/100
brijeshb42/monaco-vim#175 ·