Skip to content

Commit f077ae7

Browse files
authored
fix: improve row selection api performance (TanStack#6344)
1 parent d1c84eb commit f077ae7

12 files changed

Lines changed: 398 additions & 89 deletions

File tree

docs/framework/angular/guide/migrating.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,19 @@ Some row APIs have changed from private to public:
677677
|----|-----|
678678
| `row._getAllCellsByColumnId()` (private) | `row.getAllCellsByColumnId()` (public) |
679679

680+
### Row Selection API Changes
681+
682+
The "some rows selected" checks were simplified to mean "at least one row is selected":
683+
684+
| API | v8 | v9 |
685+
|-----|-----|-----|
686+
| `table.getIsSomeRowsSelected()` | `true` when some but not all rows are selected | `true` when at least one row is selected |
687+
| `table.getIsSomePageRowsSelected()` | `true` when some but not all page rows are selected | `true` when at least one page row is selected |
688+
689+
In v8 these returned `false` once every row was selected; in v9 they stay `true`. If you use them to drive an indeterminate "select all" checkbox, gate the indeterminate state on the matching all-selected check so it clears at full selection:
690+
691+
`getIsSomeRowsSelected() && !getIsAllRowsSelected()`
692+
680693
---
681694

682695
## TypeScript Changes Summary

docs/framework/lit/guide/migrating.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,19 @@ const features = tableFeatures({
549549

550550
Underscore-prefixed APIs that are now public should be called without `_`, such as `row.getAllCellsByColumnId()`.
551551

552+
### Row Selection API Changes
553+
554+
The "some rows selected" checks were simplified to mean "at least one row is selected":
555+
556+
| API | v8 | v9 |
557+
|-----|-----|-----|
558+
| `table.getIsSomeRowsSelected()` | `true` when some but not all rows are selected | `true` when at least one row is selected |
559+
| `table.getIsSomePageRowsSelected()` | `true` when some but not all page rows are selected | `true` when at least one page row is selected |
560+
561+
In v8 these returned `false` once every row was selected; in v9 they stay `true`. If you use them to drive an indeterminate "select all" checkbox, gate the indeterminate state on the matching all-selected check so it clears at full selection:
562+
563+
`getIsSomeRowsSelected() && !getIsAllRowsSelected()`
564+
552565
---
553566

554567
## TypeScript Changes Summary

docs/framework/preact/guide/migrating.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,19 @@ const features = tableFeatures({
532532

533533
Several underscore-prefixed APIs are now public without the underscore. For example, `row._getAllCellsByColumnId()` becomes `row.getAllCellsByColumnId()`.
534534

535+
### Row Selection API Changes
536+
537+
The "some rows selected" checks were simplified to mean "at least one row is selected":
538+
539+
| API | v8 | v9 |
540+
|-----|-----|-----|
541+
| `table.getIsSomeRowsSelected()` | `true` when some but not all rows are selected | `true` when at least one row is selected |
542+
| `table.getIsSomePageRowsSelected()` | `true` when some but not all page rows are selected | `true` when at least one page row is selected |
543+
544+
In v8 these returned `false` once every row was selected; in v9 they stay `true`. If you use them to drive an indeterminate "select all" checkbox, gate the indeterminate state on the matching all-selected check so it clears at full selection:
545+
546+
`getIsSomeRowsSelected() && !getIsAllRowsSelected()`
547+
535548
---
536549

537550
## TypeScript Changes Summary

docs/framework/react/guide/migrating.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,19 @@ Some row APIs have changed from private to public:
935935

936936
If you were accessing this internal API, you can now use it without the underscore prefix.
937937

938+
### Row Selection API Changes
939+
940+
The "some rows selected" checks were simplified to mean "at least one row is selected":
941+
942+
| API | v8 | v9 |
943+
|-----|-----|-----|
944+
| `table.getIsSomeRowsSelected()` | `true` when some but not all rows are selected | `true` when at least one row is selected |
945+
| `table.getIsSomePageRowsSelected()` | `true` when some but not all page rows are selected | `true` when at least one page row is selected |
946+
947+
In v8 these returned `false` once every row was selected; in v9 they stay `true`. If you use them to drive an indeterminate "select all" checkbox, gate the indeterminate state on the matching all-selected check so it clears at full selection:
948+
949+
`getIsSomeRowsSelected() && !getIsAllRowsSelected()`
950+
938951
---
939952

940953
## TypeScript Changes Summary

docs/framework/solid/guide/migrating.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,19 @@ const features = tableFeatures({
510510

511511
Underscore-prefixed APIs that are now public should be called without `_`, such as `row.getAllCellsByColumnId()`.
512512

513+
### Row Selection API Changes
514+
515+
The "some rows selected" checks were simplified to mean "at least one row is selected":
516+
517+
| API | v8 | v9 |
518+
|-----|-----|-----|
519+
| `table.getIsSomeRowsSelected()` | `true` when some but not all rows are selected | `true` when at least one row is selected |
520+
| `table.getIsSomePageRowsSelected()` | `true` when some but not all page rows are selected | `true` when at least one page row is selected |
521+
522+
In v8 these returned `false` once every row was selected; in v9 they stay `true`. If you use them to drive an indeterminate "select all" checkbox, gate the indeterminate state on the matching all-selected check so it clears at full selection:
523+
524+
`getIsSomeRowsSelected() && !getIsAllRowsSelected()`
525+
513526
---
514527

515528
## TypeScript Changes Summary

docs/framework/svelte/guide/migrating.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,19 @@ const features = tableFeatures({
587587

588588
Underscore-prefixed APIs that are now public should be called without `_`, such as `row.getAllCellsByColumnId()`.
589589

590+
### Row Selection API Changes
591+
592+
The "some rows selected" checks were simplified to mean "at least one row is selected":
593+
594+
| API | v8 | v9 |
595+
|-----|-----|-----|
596+
| `table.getIsSomeRowsSelected()` | `true` when some but not all rows are selected | `true` when at least one row is selected |
597+
| `table.getIsSomePageRowsSelected()` | `true` when some but not all page rows are selected | `true` when at least one page row is selected |
598+
599+
In v8 these returned `false` once every row was selected; in v9 they stay `true`. If you use them to drive an indeterminate "select all" checkbox, gate the indeterminate state on the matching all-selected check so it clears at full selection:
600+
601+
`getIsSomeRowsSelected() && !getIsAllRowsSelected()`
602+
590603
---
591604

592605
## TypeScript Changes Summary

docs/framework/vue/guide/migrating.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,19 @@ const features = tableFeatures({
533533

534534
Underscore-prefixed APIs that are now public should be called without `_`, such as `row.getAllCellsByColumnId()`.
535535

536+
### Row Selection API Changes
537+
538+
The "some rows selected" checks were simplified to mean "at least one row is selected":
539+
540+
| API | v8 | v9 |
541+
|-----|-----|-----|
542+
| `table.getIsSomeRowsSelected()` | `true` when some but not all rows are selected | `true` when at least one row is selected |
543+
| `table.getIsSomePageRowsSelected()` | `true` when some but not all page rows are selected | `true` when at least one page row is selected |
544+
545+
In v8 these returned `false` once every row was selected; in v9 they stay `true`. If you use them to drive an indeterminate "select all" checkbox, gate the indeterminate state on the matching all-selected check so it clears at full selection:
546+
547+
`getIsSomeRowsSelected() && !getIsAllRowsSelected()`
548+
536549
---
537550

538551
## TypeScript Changes Summary

examples/react/row-selection/src/main.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,10 @@ function App() {
289289
</button>
290290
</div>
291291
<div>
292-
<label>Row Selection State:</label>
293-
<pre>{JSON.stringify(table.state, null, 2)}</pre>
292+
<label>State:</label>
293+
<pre>
294+
{data.length < 1_001 && JSON.stringify(table.state, null, 2)}
295+
</pre>
294296
</div>
295297
</div>
296298
</>

packages/table-core/src/features/row-selection/rowSelectionFeature.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
table_getIsSomePageRowsSelected,
2121
table_getIsSomeRowsSelected,
2222
table_getPreSelectedRowModel,
23+
table_getSelectedRowIds,
2324
table_getSelectedRowModel,
2425
table_getToggleAllPageRowsSelectedHandler,
2526
table_getToggleAllRowsSelectedHandler,
@@ -88,10 +89,11 @@ export const rowSelectionFeature: TableFeature = {
8889
fn: (defaultState) => table_resetRowSelection(table, defaultState),
8990
},
9091
table_toggleAllRowsSelected: {
91-
fn: (value) => table_toggleAllRowsSelected(table, value),
92+
fn: (value, opts) => table_toggleAllRowsSelected(table, value, opts),
9293
},
9394
table_toggleAllPageRowsSelected: {
94-
fn: (value) => table_toggleAllPageRowsSelected(table, value),
95+
fn: (value, opts) =>
96+
table_toggleAllPageRowsSelected(table, value, opts),
9597
},
9698
table_getPreSelectedRowModel: {
9799
fn: () => table_getPreSelectedRowModel(table),
@@ -117,17 +119,37 @@ export const rowSelectionFeature: TableFeature = {
117119
table.getSortedRowModel(),
118120
],
119121
},
122+
table_getSelectedRowIds: {
123+
fn: () => table_getSelectedRowIds(table),
124+
memoDeps: () => [table.atoms.rowSelection?.get()],
125+
},
120126
table_getIsAllRowsSelected: {
121127
fn: () => table_getIsAllRowsSelected(table),
128+
memoDeps: () => [
129+
table.atoms.rowSelection?.get(),
130+
table.getFilteredRowModel(),
131+
table.options.enableRowSelection,
132+
],
122133
},
123134
table_getIsAllPageRowsSelected: {
124135
fn: () => table_getIsAllPageRowsSelected(table),
136+
memoDeps: () => [
137+
table.atoms.rowSelection?.get(),
138+
table.getPaginatedRowModel(),
139+
table.options.enableRowSelection,
140+
],
125141
},
126142
table_getIsSomeRowsSelected: {
127143
fn: () => table_getIsSomeRowsSelected(table),
144+
memoDeps: () => [table.atoms.rowSelection?.get()],
128145
},
129146
table_getIsSomePageRowsSelected: {
130147
fn: () => table_getIsSomePageRowsSelected(table),
148+
memoDeps: () => [
149+
table.atoms.rowSelection?.get(),
150+
table.getPaginatedRowModel(),
151+
table.options.enableRowSelection,
152+
],
131153
},
132154
table_getToggleAllRowsSelectedHandler: {
133155
fn: () => table_getToggleAllRowsSelectedHandler(table),

packages/table-core/src/features/row-selection/rowSelectionFeature.types.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { TableFeatures } from '../../types/TableFeatures'
33
import type { RowModel } from '../../core/row-models/coreRowModelsFeature.types'
44
import type { Row } from '../../types/Row'
55

6-
export type RowSelectionState = Record<string, boolean | undefined>
6+
export type RowSelectionState = Record<string, true>
77

88
export interface TableState_RowSelection {
99
rowSelection: RowSelectionState
@@ -98,6 +98,10 @@ export interface Table_RowSelection<
9898
* Builds a selected-row model from rows after grouping.
9999
*/
100100
getGroupedSelectedRowModel: () => RowModel<TFeatures, TData>
101+
/**
102+
* Returns the ids of all selected rows.
103+
*/
104+
getSelectedRowIds: () => Array<string>
101105
/**
102106
* Checks whether every selectable row on the current page is selected.
103107
*/
@@ -143,9 +147,15 @@ export interface Table_RowSelection<
143147
/**
144148
* Selects/deselects all rows on the current page.
145149
*/
146-
toggleAllPageRowsSelected: (value?: boolean) => void
150+
toggleAllPageRowsSelected: (
151+
value?: boolean,
152+
opts?: { deselectAll?: boolean },
153+
) => void
147154
/**
148155
* Selects/deselects all rows in the table.
149156
*/
150-
toggleAllRowsSelected: (value?: boolean) => void
157+
toggleAllRowsSelected: (
158+
value?: boolean,
159+
opts?: { deselectAll?: boolean },
160+
) => void
151161
}

0 commit comments

Comments
 (0)