mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-05-02 08:17:48 +08:00
fix: row selection leaks across pages in dataset and file list tables (#13668)
### What problem does this PR solve?
When using pagination in the Dataset file list or File Manager,
selecting row N on page 1 would incorrectly cause row N on page 2 (and
subsequent pages) to also appear selected. This is a state pollution
bug.
### Root Cause
TanStack React Table defaults to using array indices (0, 1, 2...) as
`rowSelection` keys. With server-side (manual) pagination, each page's
rows start from index 0, so a selection like `{2: true}` on page 1 also
matches index 2 on every other page.
### Fix
- Added `getRowId: (row) => row.id` to `useReactTable` in both
`DatasetTable` and `FilesTable`, so selection state is keyed by unique
document/file IDs instead of positional indices.
- Updated the `useSelectedIds` helper to support ID-based selection keys
while maintaining backward compatibility with index-based keys.
### Type of change
- [x] Bug Fix (non-breaking change which fixes an issue)
### Files Changed
| File | Change |
|------|--------|
| `web/src/pages/dataset/dataset/dataset-table.tsx` | Added `getRowId`
to table config |
| `web/src/pages/files/files-table.tsx` | Added `getRowId` to table
config |
| `web/src/hooks/logic-hooks/use-row-selection.ts` | Updated
`useSelectedIds` to handle ID-based selection |
This commit is contained in:
@ -29,10 +29,21 @@ export function useSelectedIds<T extends Array<{ id: string }>>(
|
||||
list: T,
|
||||
) {
|
||||
const selectedIds = useMemo(() => {
|
||||
const indexes = Object.keys(rowSelection);
|
||||
return list
|
||||
.filter((x, idx) => indexes.some((y) => Number(y) === idx))
|
||||
.map((x) => x.id);
|
||||
// When using getRowId, rowSelection keys are IDs, not indices
|
||||
const selectionKeys = Object.keys(rowSelection);
|
||||
|
||||
// Check if keys are numeric (index-based) or string IDs
|
||||
const isIndexBased = selectionKeys.every((key) => !isNaN(Number(key)));
|
||||
|
||||
if (isIndexBased) {
|
||||
// Legacy index-based selection
|
||||
return list
|
||||
.filter((x, idx) => selectionKeys.some((y) => Number(y) === idx))
|
||||
.map((x) => x.id);
|
||||
} else {
|
||||
// ID-based selection (when getRowId is used)
|
||||
return selectionKeys.filter((id) => list.some((item) => item.id === id));
|
||||
}
|
||||
}, [list, rowSelection]);
|
||||
|
||||
return { selectedIds };
|
||||
|
||||
@ -114,6 +114,7 @@ export function DatasetTable({
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
onColumnVisibilityChange: setColumnVisibility,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
getRowId: (row) => row.id, // Use document ID instead of row index
|
||||
manualPagination: true, //we're doing manual "server-side" pagination
|
||||
state: {
|
||||
sorting,
|
||||
|
||||
@ -260,7 +260,7 @@ export function FilesTable({
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
onColumnVisibilityChange: setColumnVisibility,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
|
||||
getRowId: (row) => row.id, // Use file ID instead of row index
|
||||
manualPagination: true, //we're doing manual "server-side" pagination
|
||||
enableRowSelection(row) {
|
||||
return !isKnowledgeBaseType(row.original.source_type);
|
||||
|
||||
Reference in New Issue
Block a user