Infinite scroll and virtualization lag
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 35/100
- Tipo di issue
- Bug
- Chiarezza
- Da chiarire
- Stato di attività
- Ferma
- Stack tecnologico
- react, typescript
- Ambito
- frontend, performance
Direzione di ricerca
Inizia con il codice fornito di CandidatesListTable e DataTable, concentrandoti sulla configurazione di @tanstack/react-virtual, su tableContainerRef e sul percorso handleScroll di ScrollArea. Riproduci la chiamata API di infinite scroll durante lo scorrimento, quindi determina se l’elemento di scorrimento e il comportamento della virtualizzazione corrispondono agli esempi. Il lavoro è completato quando lo scorrimento è fluido durante il recupero delle pagine e la virtualizzazione funziona.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
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.
- Lingua principale
- TypeScript
- Stelle
- 7.1k
- Fork
- 472
- Merge medio
- 1g 1h
- PR unite (30g)
- 11
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di TanStack/virtual
-
measureElement caches 0 size for nodes that aren't attached yet (Vue: rows stack at start 0 and the list scrolls away on mount)Forse già presa @webn00b l’ha presa 11 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
anchorTo: 'end' loses the end when the scroll element shrinksForse già presa @langleyd l’ha presa oggi. Aperta
Difficoltà 3/5 1-2 giorni Idoneità per principianti 68/100
I maintainer di solito rispondono entro 1 giorno
-
`scrollToIndex(last, { align: 'end' })` stays short of the end after a measured row grows (virtual-core ≥ 3.17.0)Forse già presa @minwookshin l’ha presa 9 giorni fa. Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 55/100
TanStack/virtual#1290 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
virtual-core: desktop Safari drops the prepend anchor write when history lands during the top rubber-band bounceForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 5/5 Più di una settimana Idoneità per principianti 38/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 62/100
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di TanStack/virtual
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
kind/chore priority/must
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
sidereal-io/sidereal#380 ·
I maintainer di solito rispondono entro 1 giorno
-
Mend: dependency security vulnerability
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
opfab/operatorfabric-core#10653 ·
I maintainer di solito rispondono entro 1 giorno
-
backend bug size:sm
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
chrisbenincasa/tunarr#2237 ·
I maintainer di solito rispondono entro 1 giorno
-
documentation
Difficoltà 2/5 Mezza giornata Idoneità per principianti 69/100
Lam30ne/regulate-app#39 ·