diff --git a/web/default/src/components/data-table/core/data-table-row.tsx b/web/default/src/components/data-table/core/data-table-row.tsx index 9973e419..0730380e 100644 --- a/web/default/src/components/data-table/core/data-table-row.tsx +++ b/web/default/src/components/data-table/core/data-table-row.tsx @@ -29,15 +29,20 @@ type DataTableRowProps = { getColumnClassName?: DataTableColumnClassName } & Omit, 'children'> +type DataTableRowInnerProps = DataTableRowProps & { + isSelected: boolean +} + function DataTableRowInner({ row, + isSelected, className, getColumnClassName, ...rowProps -}: DataTableRowProps) { +}: DataTableRowInnerProps) { return ( @@ -56,17 +61,23 @@ function DataTableRowInner({ ) } -export const DataTableRow = React.memo(DataTableRowInner, (prev, next) => { - // Skip re-render when only the getColumnClassName reference changed but the - // row identity and selection state are the same — callers rarely stabilize - // this callback, so excluding it from comparison avoids unnecessary renders. +const MemoizedDataTableRow = React.memo(DataTableRowInner, (prev, next) => { + // Do not read row.getIsSelected() here: TanStack row objects may keep a stable + // reference while their selection state changes. return ( prev.row === next.row && prev.className === next.className && - prev.row.getIsSelected() === next.row.getIsSelected() + prev.getColumnClassName === next.getColumnClassName && + prev.isSelected === next.isSelected ) }) as typeof DataTableRowInner +export function DataTableRow(props: DataTableRowProps) { + return ( + + ) +} + function renderCellContent(cell: Cell) { const content = flexRender(cell.column.columnDef.cell, cell.getContext()) const textContent = getPrimitiveTextContent(content)