@tanstack/react-table 8.0.0-alpha.5 → 8.0.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/build/cjs/core.js +19 -11
  2. package/build/cjs/core.js.map +1 -1
  3. package/build/cjs/createTable.js +10 -10
  4. package/build/cjs/createTable.js.map +1 -1
  5. package/build/cjs/features/Expanding.js +5 -9
  6. package/build/cjs/features/Expanding.js.map +1 -1
  7. package/build/cjs/features/Filters.js +3 -3
  8. package/build/cjs/features/Filters.js.map +1 -1
  9. package/build/cjs/features/Grouping.js +2 -2
  10. package/build/cjs/features/Grouping.js.map +1 -1
  11. package/build/cjs/features/Pagination.js +2 -2
  12. package/build/cjs/features/Pagination.js.map +1 -1
  13. package/build/cjs/features/Pinning.js +2 -2
  14. package/build/cjs/features/Pinning.js.map +1 -1
  15. package/build/cjs/features/Sorting.js +2 -2
  16. package/build/cjs/features/Sorting.js.map +1 -1
  17. package/build/cjs/utils.js +9 -14
  18. package/build/cjs/utils.js.map +1 -1
  19. package/build/esm/index.js +54 -55
  20. package/build/esm/index.js.map +1 -1
  21. package/build/stats-html.html +1 -1
  22. package/build/stats-react.json +259 -245
  23. package/build/types/core.d.ts +3 -4
  24. package/build/types/utils.d.ts +0 -4
  25. package/build/umd/index.development.js +57 -59
  26. package/build/umd/index.development.js.map +1 -1
  27. package/build/umd/index.production.js +1 -1
  28. package/build/umd/index.production.js.map +1 -1
  29. package/package.json +7 -1
  30. package/src/core.tsx +16 -101
  31. package/src/createTable.tsx +16 -13
  32. package/src/features/Expanding.ts +5 -3
  33. package/src/features/Filters.ts +4 -4
  34. package/src/features/Grouping.ts +1 -1
  35. package/src/features/Pagination.ts +1 -3
  36. package/src/features/Pinning.ts +1 -3
  37. package/src/features/Sorting.ts +1 -1
  38. package/src/utils.tsx +7 -69
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tanstack/react-table",
3
3
  "author": "Tanner Linsley",
4
- "version": "8.0.0-alpha.5",
4
+ "version": "8.0.0-alpha.8",
5
5
  "description": "Hooks for building lightweight, fast and extendable datagrids for React",
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/tanstack/react-table#readme",
@@ -36,5 +36,11 @@
36
36
  "peerDependencies": {
37
37
  "react": ">=16",
38
38
  "react-dom": ">=16"
39
+ },
40
+ "dependencies": {
41
+ "use-sync-external-store": "^1.0.0-rc.0"
42
+ },
43
+ "devDependencies": {
44
+ "@types/use-sync-external-store": "^0.0.3"
39
45
  }
40
46
  }
package/src/core.tsx CHANGED
@@ -84,7 +84,8 @@ export type CoreOptions<
84
84
 
85
85
  export type TableCore<TData, TValue, TFilterFns, TSortingFns, TAggregationFns> =
86
86
  {
87
- rerender: () => void
87
+ subscribe: (cb: () => void) => () => void
88
+ notify: () => void
88
89
  initialState: TableState
89
90
  internalState: TableState
90
91
  reset: () => void
@@ -291,96 +292,6 @@ export type CoreColumnDef<
291
292
  header: Header<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
292
293
  column: Column<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
293
294
  }>
294
- } & // instance: ReactTable< // | Renderable<{ // | string // header?: // accessorKey?: never // id: string // accessorFn: AccessorFn<TData> // | {
295
- // TData,
296
- // TValue,
297
- // TFilterFns,
298
- // TSortingFns,
299
- // TAggregationFns
300
- // >
301
- // header: Header<
302
- // TData,
303
- // TValue,
304
- // TFilterFns,
305
- // TSortingFns,
306
- // TAggregationFns
307
- // >
308
- // column: Column<
309
- // TData,
310
- // TValue,
311
- // TFilterFns,
312
- // TSortingFns,
313
- // TAggregationFns
314
- // >
315
- // }>
316
- // }
317
- // | {
318
- // accessorKey: string & keyof TData
319
- // id?: string
320
- // accessorFn?: never
321
- // header?:
322
- // | string
323
- // | Renderable<{
324
- // instance: ReactTable<
325
- // TData,
326
- // TValue,
327
- // TFilterFns,
328
- // TSortingFns,
329
- // TAggregationFns
330
- // >
331
- // header: Header<
332
- // TData,
333
- // TValue,
334
- // TFilterFns,
335
- // TSortingFns,
336
- // TAggregationFns
337
- // >
338
- // column: Column<
339
- // TData,
340
- // TValue,
341
- // TFilterFns,
342
- // TSortingFns,
343
- // TAggregationFns
344
- // >
345
- // }>
346
- // }
347
- // | {
348
- // id: string
349
- // accessorKey?: never
350
- // accessorFn?: never
351
- // header?:
352
- // | string
353
- // | Renderable<{
354
- // instance: ReactTable<
355
- // TData,
356
- // TValue,
357
- // TFilterFns,
358
- // TSortingFns,
359
- // TAggregationFns
360
- // >
361
- // header: Header<
362
- // TData,
363
- // TValue,
364
- // TFilterFns,
365
- // TSortingFns,
366
- // TAggregationFns
367
- // >
368
- // column: Column<
369
- // TData,
370
- // TValue,
371
- // TFilterFns,
372
- // TSortingFns,
373
- // TAggregationFns
374
- // >
375
- // }>
376
- // }
377
- // | {
378
- // header: string
379
- // id?: string
380
- // accessorKey?: never
381
- // accessorFn?: never
382
- // }
383
- {
384
295
  __generated: true
385
296
  width?: number
386
297
  minWidth?: number
@@ -450,8 +361,7 @@ export function createTableInstance<
450
361
  TSortingFns,
451
362
  TAggregationFns
452
363
  >(
453
- options: Options<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>,
454
- rerender: () => void
364
+ options: Options<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
455
365
  ): ReactTable<TData, TValue, TFilterFns, TSortingFns, TAggregationFns> {
456
366
  if (process.env.NODE_ENV !== 'production' && options.debug) {
457
367
  console.info('Creating React Table Instance...')
@@ -465,6 +375,8 @@ export function createTableInstance<
465
375
  TAggregationFns
466
376
  >
467
377
 
378
+ let listeners: (() => void)[] = []
379
+
468
380
  const defaultOptions = features.reduce((obj, feature) => {
469
381
  return Object.assign(obj, (feature as any).getDefaultOptions?.(instance))
470
382
  }, {})
@@ -496,10 +408,18 @@ export function createTableInstance<
496
408
  TAggregationFns
497
409
  > = {
498
410
  ...instance,
411
+ subscribe: cb => {
412
+ listeners.push(cb)
413
+ return () => {
414
+ listeners = listeners.filter(l => l !== cb)
415
+ }
416
+ },
417
+ notify: () => {
418
+ listeners.forEach(l => l())
419
+ },
499
420
  ...features.reduce((obj, feature) => {
500
421
  return Object.assign(obj, (feature as any).getInstance?.(instance))
501
422
  }, {}),
502
- rerender,
503
423
  initialState,
504
424
  internalState: initialState,
505
425
  reset: () => {
@@ -524,10 +444,7 @@ export function createTableInstance<
524
444
  return state
525
445
  },
526
446
 
527
- setState: (
528
- updater: Updater<TableState>,
529
- shouldRerender: boolean = true
530
- ) => {
447
+ setState: (updater: Updater<TableState>) => {
531
448
  const onStateChange = instance.options.onStateChange
532
449
 
533
450
  let internalState = instance.internalState
@@ -540,9 +457,7 @@ export function createTableInstance<
540
457
  return
541
458
  }
542
459
 
543
- if (shouldRerender) {
544
- instance.rerender()
545
- }
460
+ instance.notify()
546
461
  },
547
462
 
548
463
  getDefaultColumn: memo(
@@ -1,4 +1,5 @@
1
1
  import * as React from 'react'
2
+ import { useSyncExternalStore } from 'use-sync-external-store/shim'
2
3
  import { Cell, Column, Row } from '.'
3
4
  import { createTableInstance } from './core'
4
5
  import {
@@ -11,7 +12,13 @@ import {
11
12
  } from './types'
12
13
  import { Overwrite } from './utils'
13
14
 
14
- export type TableHelper<TData, TValue, TFilterFns, TSortingFns, TAggregationFns> = {
15
+ export type TableHelper<
16
+ TData,
17
+ TValue,
18
+ TFilterFns,
19
+ TSortingFns,
20
+ TAggregationFns
21
+ > = {
15
22
  RowType<TTData>(): TableHelper<
16
23
  TTData,
17
24
  TValue,
@@ -216,25 +223,21 @@ export function createTable<
216
223
  useTable: <TData, TValue, TFilterFns, TSortingFns, TAggregationFns>(
217
224
  options: Options<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
218
225
  ): ReactTable<TData, TValue, TFilterFns, TSortingFns, TAggregationFns> => {
219
- const instanceRef = React.useRef<
220
- ReactTable<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
221
- >(undefined!)
222
-
223
- const rerender = React.useReducer(() => ({}), {})[1]
224
-
225
- if (!instanceRef.current) {
226
- instanceRef.current = createTableInstance<
226
+ const [instance] = React.useState(() =>
227
+ createTableInstance<
227
228
  TData,
228
229
  TValue,
229
230
  TFilterFns,
230
231
  TSortingFns,
231
232
  TAggregationFns
232
- >(options, rerender)
233
- }
233
+ >(options)
234
+ )
235
+
236
+ useSyncExternalStore(instance.subscribe, () => instance.internalState)
234
237
 
235
- instanceRef.current.updateOptions(options)
238
+ instance.updateOptions(options)
236
239
 
237
- return instanceRef.current
240
+ return instance
238
241
  },
239
242
  types: undefined as any,
240
243
  } as TableHelper<TData, TValue, TFilterFns, TSortingFns, TAggregationFns>
@@ -192,7 +192,7 @@ export function getInstance<
192
192
  toggleRowExpanded: (rowId, expanded) => {
193
193
  if (!rowId) return
194
194
 
195
- instance.setExpanded((old = {}) => {
195
+ instance.setExpanded(old => {
196
196
  const exists = old === true ? true : !!old?.[rowId]
197
197
 
198
198
  let oldExpanded: ExpandedStateList = {}
@@ -230,7 +230,7 @@ export function getInstance<
230
230
  }
231
231
  },
232
232
  resetExpanded: () => {
233
- instance.setExpanded(instance.options?.initialState?.expanded ?? {})
233
+ instance.setExpanded(instance.initialState?.expanded ?? {})
234
234
  },
235
235
  getIsRowExpanded: rowId => {
236
236
  const row = instance.getRow(rowId)
@@ -362,7 +362,9 @@ export function getInstance<
362
362
  {
363
363
  key: 'getExpandedRowModel',
364
364
  debug: instance.options.debug,
365
- onChange: () => instance._notifyPageIndexReset(),
365
+ onChange: () => {
366
+ instance._notifyPageIndexReset()
367
+ },
366
368
  }
367
369
  ),
368
370
 
@@ -628,9 +628,7 @@ export function getInstance<
628
628
  },
629
629
 
630
630
  resetColumnFilters: () => {
631
- instance.setColumnFilters(
632
- instance.options?.initialState?.columnFilters ?? []
633
- )
631
+ instance.setColumnFilters(instance.initialState?.columnFilters ?? [])
634
632
  },
635
633
 
636
634
  getColumnFilteredRowModel: memo(
@@ -730,7 +728,9 @@ export function getInstance<
730
728
  {
731
729
  key: 'getGlobalFilteredRowModel',
732
730
  debug: instance.options.debug,
733
- onChange: () => instance._notifySortingReset(),
731
+ onChange: () => {
732
+ instance._notifySortingReset()
733
+ },
734
734
  }
735
735
  ),
736
736
 
@@ -331,7 +331,7 @@ export function getInstance<
331
331
  instance.getState().grouping?.indexOf(columnId),
332
332
 
333
333
  resetGrouping: () => {
334
- instance.setGrouping(instance.options?.initialState?.grouping ?? [])
334
+ instance.setGrouping(instance.initialState?.grouping ?? [])
335
335
  },
336
336
 
337
337
  getToggleGroupingProps: (columnId, userProps) => {
@@ -217,9 +217,7 @@ export function getInstance<
217
217
  instance.setPageIndex(0)
218
218
  },
219
219
  resetPageSize: () => {
220
- instance.setPageSize(
221
- instance.options.initialState?.pagination?.pageSize ?? 10
222
- )
220
+ instance.setPageSize(instance.initialState?.pagination?.pageSize ?? 10)
223
221
  },
224
222
  setPageSize: updater => {
225
223
  instance.setPagination(old => {
@@ -114,9 +114,7 @@ export function getInstance<
114
114
  ),
115
115
 
116
116
  resetColumnPinning: () =>
117
- instance.setColumnPinning(
118
- instance.options.initialState?.columnPinning ?? {}
119
- ),
117
+ instance.setColumnPinning(instance.initialState?.columnPinning ?? {}),
120
118
 
121
119
  pinColumn: (columnId, position) => {
122
120
  const column = instance.getColumn(columnId)
@@ -484,7 +484,7 @@ export function getInstance<
484
484
  instance.getState().sorting?.findIndex(d => d.id === columnId) ?? -1,
485
485
 
486
486
  resetSorting: () => {
487
- instance.setSorting(instance.options?.initialState?.sorting ?? [])
487
+ instance.setSorting(instance.initialState?.sorting ?? [])
488
488
  },
489
489
 
490
490
  getToggleSortingProps: (columnId, userProps) => {
package/src/utils.tsx CHANGED
@@ -43,29 +43,6 @@ export function makeStateUpdater(key: keyof TableState, instance: unknown) {
43
43
  }
44
44
  }
45
45
 
46
- // SSR has issues with useLayoutEffect still, so use useEffect during SSR
47
- export const safeUseLayoutEffect =
48
- typeof document !== 'undefined' ? React.useLayoutEffect : React.useEffect
49
-
50
- export function useMountedLayoutEffect(fn: any, deps: any[]) {
51
- const mountedRef = React.useRef(false)
52
-
53
- safeUseLayoutEffect(() => {
54
- if (mountedRef.current) {
55
- fn()
56
- }
57
- mountedRef.current = true
58
- // eslint-disable-next-line
59
- }, deps)
60
- }
61
-
62
- export function useGetLatest<T>(obj: T): () => T {
63
- const ref = React.useRef<T>()
64
- ref.current = obj
65
-
66
- return React.useCallback(() => ref.current!, [])
67
- }
68
-
69
46
  type AnyFunction = (...args: any) => any
70
47
 
71
48
  export function isFunction<T extends AnyFunction>(d: any): d is T {
@@ -124,27 +101,19 @@ export function memo<TDeps extends readonly any[], TResult>(
124
101
 
125
102
  return () => {
126
103
  const newDeps = getDeps()
127
- const newSerializedDeps = newDeps
128
- const oldSerializedDeps = deps
129
104
 
130
105
  const depsChanged =
131
- newSerializedDeps.length !== oldSerializedDeps.length ||
132
- newSerializedDeps.some(
133
- (dep: any, index: number) => oldSerializedDeps[index] !== dep
134
- )
106
+ newDeps.length !== deps.length ||
107
+ newDeps.some((dep: any, index: number) => deps[index] !== dep)
135
108
 
136
109
  if (depsChanged) {
137
110
  if (opts?.debug) {
138
111
  console.info(opts?.key, {
139
- length: `${oldSerializedDeps.length} -> ${newSerializedDeps.length}`,
140
- ...newSerializedDeps
112
+ length: `${deps.length} -> ${newDeps.length}`,
113
+ ...newDeps
141
114
  .map((_, index) => {
142
- if (oldSerializedDeps[index] !== newSerializedDeps[index]) {
143
- return [
144
- index,
145
- oldSerializedDeps[index],
146
- newSerializedDeps[index],
147
- ]
115
+ if (deps[index] !== newDeps[index]) {
116
+ return [index, deps[index], newDeps[index]]
148
117
  }
149
118
 
150
119
  return false
@@ -163,7 +132,7 @@ export function memo<TDeps extends readonly any[], TResult>(
163
132
 
164
133
  let oldResult = result
165
134
  result = fn(...newDeps)
166
- deps = newSerializedDeps
135
+ deps = newDeps
167
136
  opts?.onChange?.(result, oldResult)
168
137
 
169
138
  oldResult = undefined
@@ -173,37 +142,6 @@ export function memo<TDeps extends readonly any[], TResult>(
173
142
  }
174
143
  }
175
144
 
176
- // Copied from: https://github.com/jonschlinkert/is-plain-object
177
- export function isPlainObject(o: any): o is Object {
178
- if (!hasObjectPrototype(o)) {
179
- return false
180
- }
181
-
182
- // If has modified constructor
183
- const ctor = o.constructor
184
- if (typeof ctor === 'undefined') {
185
- return true
186
- }
187
-
188
- // If has modified prototype
189
- const prot = ctor.prototype
190
- if (!hasObjectPrototype(prot)) {
191
- return false
192
- }
193
-
194
- // If constructor does not have an Object-specific method
195
- if (!prot.hasOwnProperty('isPrototypeOf')) {
196
- return false
197
- }
198
-
199
- // Most likely a plain Object
200
- return true
201
- }
202
-
203
- function hasObjectPrototype(o: any): boolean {
204
- return Object.prototype.toString.call(o) === '[object Object]'
205
- }
206
-
207
145
  export type Render = typeof flexRender
208
146
 
209
147
  export function flexRender<TProps extends {}>(