diff --git a/packages/table-core/src/core/table.ts b/packages/table-core/src/core/table.ts index 00d62da98f..f5a3bad2e7 100644 --- a/packages/table-core/src/core/table.ts +++ b/packages/table-core/src/core/table.ts @@ -323,6 +323,29 @@ export function createTable( const queued: (() => void)[] = [] let queuedTimeout = false + let getColumnCache = new WeakMap< + ColumnDef[], + Record> + >() + + const getColumnFromCache = (columnId: string) => { + const columnDefs = table.options.columns + let columnsById = getColumnCache.get(columnDefs) + + if (!columnsById) { + columnsById = table.getAllFlatColumns().reduce( + (acc, column) => { + acc[column.id] = column + return acc + }, + {} as Record> + ) + + getColumnCache.set(columnDefs, columnsById) + } + + return columnsById[columnId] + } const coreInstance: CoreInstance = { _features, @@ -506,7 +529,7 @@ export function createTable( ), getColumn: columnId => { - const column = table._getAllFlatColumnsById()[columnId] + const column = getColumnFromCache(columnId) if (process.env.NODE_ENV !== 'production' && !column) { console.error(`[Table] Column with id '${columnId}' does not exist.`) diff --git a/packages/table-core/tests/coreTable.test.ts b/packages/table-core/tests/coreTable.test.ts new file mode 100644 index 0000000000..48a480ac75 --- /dev/null +++ b/packages/table-core/tests/coreTable.test.ts @@ -0,0 +1,48 @@ +import { describe, expect, it } from 'vitest' +import { ColumnDef, createTable, getCoreRowModel } from '../src' + +type Person = { + firstName: string + lastName: string +} + +describe('CoreTable', () => { + it('refreshes the column lookup cache when columns change without data changing', () => { + const data: Person[] = [{ firstName: 'Ada', lastName: 'Lovelace' }] + const firstNameColumns: ColumnDef[] = [ + { + id: 'name', + accessorFn: row => row.firstName, + }, + ] + const lastNameColumns: ColumnDef[] = [ + { + id: 'name', + accessorFn: row => row.lastName, + }, + ] + + const table = createTable({ + onStateChange() {}, + renderFallbackValue: '', + data, + state: {}, + columns: firstNameColumns, + getCoreRowModel: getCoreRowModel(), + }) + + const firstColumn = table.getColumn('name') + const row = table.getCoreRowModel().rows[0]! + + expect(row.getValue('name')).toBe('Ada') + + table.setOptions(old => ({ + ...old, + columns: lastNameColumns, + })) + + expect(table.getCoreRowModel().rows[0]).toBe(row) + expect(table.getColumn('name')).not.toBe(firstColumn) + expect(row.getValue('name')).toBe('Lovelace') + }) +})