mirror of
https://github.com/docmost/docmost.git
synced 2026-05-07 06:23:06 +08:00
fix(base): stop infinite fetch loop when sorted list scrolled to bottom
This commit is contained in:
@@ -60,6 +60,14 @@ export function GridContainer({
|
|||||||
onFetchNextPage,
|
onFetchNextPage,
|
||||||
}: GridContainerProps) {
|
}: GridContainerProps) {
|
||||||
const scrollRef = useRef<HTMLDivElement>(null);
|
const scrollRef = useRef<HTMLDivElement>(null);
|
||||||
|
// Records the `rows.length` at which we last triggered a page fetch.
|
||||||
|
// The trigger effect re-runs on every render (its `virtualItems` dep
|
||||||
|
// has a new identity each call) and can't rely on `isFetchingNextPage`
|
||||||
|
// alone: once a page commits, `isFetchingNextPage` flips to false for
|
||||||
|
// one render, the "near bottom" condition still holds because the
|
||||||
|
// virtualizer anchors on the old scroll position, and we'd fire again.
|
||||||
|
// Gating on `rows.length` guarantees at most one fire per new page.
|
||||||
|
const lastTriggeredRowsLenRef = useRef(0);
|
||||||
const rows = table.getRowModel().rows;
|
const rows = table.getRowModel().rows;
|
||||||
|
|
||||||
const [editingCell, setEditingCell] = useAtom(editingCellAtom) as unknown as [EditingCell, (val: EditingCell) => void];
|
const [editingCell, setEditingCell] = useAtom(editingCellAtom) as unknown as [EditingCell, (val: EditingCell) => void];
|
||||||
@@ -115,11 +123,22 @@ export function GridContainer({
|
|||||||
if (!hasNextPage || isFetchingNextPage || !onFetchNextPage) return;
|
if (!hasNextPage || isFetchingNextPage || !onFetchNextPage) return;
|
||||||
const lastItem = virtualItems[virtualItems.length - 1];
|
const lastItem = virtualItems[virtualItems.length - 1];
|
||||||
if (!lastItem) return;
|
if (!lastItem) return;
|
||||||
if (lastItem.index >= rows.length - OVERSCAN * 2) {
|
if (lastItem.index < rows.length - OVERSCAN * 2) return;
|
||||||
|
if (rows.length <= lastTriggeredRowsLenRef.current) return;
|
||||||
|
lastTriggeredRowsLenRef.current = rows.length;
|
||||||
onFetchNextPage();
|
onFetchNextPage();
|
||||||
}
|
|
||||||
}, [virtualItems, rows.length, hasNextPage, isFetchingNextPage, onFetchNextPage]);
|
}, [virtualItems, rows.length, hasNextPage, isFetchingNextPage, onFetchNextPage]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// When the underlying row set shrinks (filter changed, sort toggled,
|
||||||
|
// view switched) or resets to zero, we're on a fresh pagination
|
||||||
|
// sequence — un-gate the trigger so the first page triggers a
|
||||||
|
// potential next fetch correctly.
|
||||||
|
if (rows.length === 0 || rows.length < lastTriggeredRowsLenRef.current) {
|
||||||
|
lastTriggeredRowsLenRef.current = 0;
|
||||||
|
}
|
||||||
|
}, [rows.length]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const el = scrollRef.current;
|
const el = scrollRef.current;
|
||||||
if (!el || !baseId) return;
|
if (!el || !baseId) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user