diff --git a/packages/client/src/components/DataTable/DataTable.tsx b/packages/client/src/components/DataTable/DataTable.tsx index e9e1c0e37a..de7bca3d26 100644 --- a/packages/client/src/components/DataTable/DataTable.tsx +++ b/packages/client/src/components/DataTable/DataTable.tsx @@ -10,7 +10,7 @@ import { type ColumnDef, type Row, } from '@tanstack/react-table'; -import type { DataTableProps, ProcessedDataRow, TableColumnDef } from './DataTable.types'; +import type { DataTableProps, ProcessedDataRow } from './DataTable.types'; import { SelectionCheckbox, MemoizedTableRow, SkeletonRows } from './DataTableComponents'; import { Table, TableBody, TableHead, TableHeader, TableCell, TableRow } from '../Table'; import { useDebounced, useOptimizedRowSelection } from './DataTable.hooks'; @@ -75,6 +75,17 @@ function DataTable, TValue>({ const debouncedTerm = useDebounced(searchTerm, debounceDelay); const finalSorting = sorting ?? internalSorting; + const processedData = useMemo[]>(() => { + return data.map((item, index) => { + const id = item.id; + return { + ...item, + _id: String(id ?? `row-${index}`), + _index: index, + }; + }); + }, [data]); + const calculatedVisibility = useMemo(() => { const newVisibility: VisibilityState = {}; columns.forEach((col) => { @@ -101,28 +112,24 @@ function DataTable, TValue>({ setColumnVisibility((prev) => ({ ...prev, ...calculatedVisibility })); }, [calculatedVisibility]); - const processedData = useMemo( - () => - data.map((item, index): ProcessedDataRow => { - if (item.id === null || item.id === undefined) { - logger.warn( - 'DataTable Warning: A data row is missing a unique "id" property. Using index as a fallback. This can lead to unexpected behavior with selection and sorting.', - item, - ); - } + const hasWarnedAboutMissingIds = useRef(false); - return { - ...item, - _index: index, - _id: String(item.id ?? `row-${index}`), - }; - }), - [data], - ); + useEffect(() => { + if (data.length > 0 && !hasWarnedAboutMissingIds.current) { + const missing = data.filter((item) => item.id === null || item.id === undefined); + if (missing.length > 0) { + logger.warn( + `DataTable Warning: ${missing.length} data rows are missing a unique "id" property. Using index as a fallback. This can lead to unexpected behavior with selection and sorting.`, + { missingCount: missing.length, sample: missing.slice(0, 3) }, + ); + hasWarnedAboutMissingIds.current = true; + } + } + }, [data]); - const tableColumns = useMemo((): TableColumnDef[] => { + const tableColumns = useMemo((): ColumnDef, TValue>[] => { if (!enableRowSelection || !showCheckboxes) { - return columns as TableColumnDef[]; + return columns.map((col) => col as unknown as ColumnDef, TValue>); } const selectColumn: ColumnDef, TValue> = { @@ -148,9 +155,12 @@ function DataTable, TValue>({ meta: { className: 'w-12', }, - } as TableColumnDef; + }; - return [selectColumn, ...(columns as TableColumnDef[])]; + return [ + selectColumn, + ...columns.map((col) => col as unknown as ColumnDef, TValue>), + ]; }, [columns, enableRowSelection, showCheckboxes, localize]); const table = useReactTable>({ @@ -240,7 +250,7 @@ function DataTable, TValue>({ } scrollTimeoutRef.current = null; - }, 150); + }, 50); scrollRAFRef.current = null; }); @@ -288,7 +298,7 @@ function DataTable, TValue>({ {customActionsRenderer && customActionsRenderer({ selectedCount, - selectedRows: table.getSelectedRowModel().rows.map((r) => r.original), + selectedRows: table.getSelectedRowModel().rows.map((r) => r.original as TData), table, })} @@ -375,9 +385,7 @@ function DataTable, TValue>({ return ( >} - columns={tableColumns as ColumnDef>[]} - index={virtualRow.index} + row={row as unknown as Row} virtualIndex={virtualRow.index} /> ); diff --git a/packages/client/src/components/DataTable/DataTableComponents.tsx b/packages/client/src/components/DataTable/DataTableComponents.tsx index 96474aaa11..d1cd457a6a 100644 --- a/packages/client/src/components/DataTable/DataTableComponents.tsx +++ b/packages/client/src/components/DataTable/DataTableComponents.tsx @@ -1,7 +1,7 @@ import { memo } from 'react'; import { flexRender } from '@tanstack/react-table'; -import type { Row, ColumnDef } from '@tanstack/react-table'; import type { TableColumn } from './DataTable.types'; +import type { Row } from '@tanstack/react-table'; import { TableCell, TableRow } from '../Table'; import { Checkbox } from '../Checkbox'; import { Skeleton } from '../Skeleton'; @@ -45,8 +45,6 @@ const TableRowComponent = >({ virtualIndex, }: { row: Row; - columns: ColumnDef[]; - index: number; virtualIndex?: number; }) => ( prev.row.original === next.row.original && - prev.row.getIsSelected() === next.row.getIsSelected() && - prev.columns === next.columns, + prev.row.getIsSelected() === next.row.getIsSelected(), ); export const SkeletonRows = memo(