Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Infinite scroll and virtualization lag

未关闭
#729 2 条评论 1 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
35/100
Issue 类型
缺陷
描述清晰度
需要澄清
活跃度
停滞
技术栈
react, typescript

调研方向

从提供的 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.1k
派生
472
平均合并
1 天 1 小时
30 天内合并 PR
11

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

TanStack/virtual 的其他 Issue

查看 TanStack/virtual 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。