diff --git a/packages/table-core/src/core/columns/constructColumn.ts b/packages/table-core/src/core/columns/constructColumn.ts index b9bb8975ac..4ee316307f 100644 --- a/packages/table-core/src/core/columns/constructColumn.ts +++ b/packages/table-core/src/core/columns/constructColumn.ts @@ -112,7 +112,7 @@ export function constructColumn< column.columnDef = resolvedColumnDef as ColumnDef column.columns = [] column.depth = depth - column.id = `${String(id)}` + column.id = '' + id column.parent = parent // Initialize instance-specific data for features that need it diff --git a/packages/table-core/src/core/columns/coreColumnsFeature.utils.ts b/packages/table-core/src/core/columns/coreColumnsFeature.utils.ts index 2fae8a1fd7..b356690413 100644 --- a/packages/table-core/src/core/columns/coreColumnsFeature.utils.ts +++ b/packages/table-core/src/core/columns/coreColumnsFeature.utils.ts @@ -29,7 +29,9 @@ export function column_getFlatColumns< >( column: Column, ): Array> { - return [column, ...column.columns.flatMap((col) => col.getFlatColumns())] + const arr = column.columns.flatMap((col) => col.getFlatColumns()) + arr.unshift(column) + return arr } /** @@ -65,6 +67,28 @@ export function column_getLeafColumns< return [column] } +const defaultColumnDef_header: Partial< + ColumnDef +>['header'] = (props) => { + const resolvedColumnDef = props.header.column.columnDef as ColumnDefResolved< + {}, + any + > + + if (resolvedColumnDef.accessorKey) { + return resolvedColumnDef.accessorKey + } + + if (resolvedColumnDef.accessorFn) { + return resolvedColumnDef.id + } + + return null +} +const defaultColumnDef_cell: Partial>['cell'] = ( + props, +) => props.renderValue()?.toString?.() ?? null + /** * Merges built-in, feature, and user default column definitions. * @@ -83,27 +107,59 @@ export function table_getDefaultColumnDef< >( table: Table_Internal, ): Partial> { - return { - header: (props) => { - const resolvedColumnDef = props.header.column - .columnDef as ColumnDefResolved<{}, TData> + const defaultColumn = { + header: defaultColumnDef_header, + cell: defaultColumnDef_cell, + } + + for ( + let i = 0, features = Object.values(table._features); + i < features.length; + i++ + ) { + Object.assign(defaultColumn, features[i].getDefaultColumnDef?.()) + } + + return Object.assign(defaultColumn, table.options.defaultColumn) +} + +const table_getAllColumns_recurseColumns = < + TFeatures extends TableFeatures, + TData extends RowData, +>( + table: Table_Internal, + colDefs: ReadonlyArray>, + parent: Column | undefined, + depth: number, +): Array> => { + const result: Array> = new Array( + colDefs.length, + ) + + for (let i = 0; i < colDefs.length; i++) { + const columnDef = colDefs[i]! - if (resolvedColumnDef.accessorKey) { - return resolvedColumnDef.accessorKey - } + const column = constructColumn(table, columnDef, depth, parent) - if (resolvedColumnDef.accessorFn) { - return resolvedColumnDef.id - } + const groupingColumnDef = columnDef as GroupColumnDef< + TFeatures, + TData, + unknown + > - return null - }, - cell: (props) => props.renderValue()?.toString?.() ?? null, - ...Object.values(table._features).reduce((obj, feature) => { - return Object.assign(obj, feature.getDefaultColumnDef?.()) - }, {}), - ...table.options.defaultColumn, - } as Partial> + column.columns = groupingColumnDef.columns + ? table_getAllColumns_recurseColumns( + table, + groupingColumnDef.columns, + column, + depth + 1, + ) + : [] + + result[i] = column + } + + return result } /** @@ -123,29 +179,12 @@ export function table_getAllColumns< >( table: Table_Internal, ): Array> { - const recurseColumns = ( - colDefs: ReadonlyArray>, - parent?: Column, - depth = 0, - ): Array> => { - return colDefs.map((columnDef) => { - const column = constructColumn(table, columnDef, depth, parent) - - const groupingColumnDef = columnDef as GroupColumnDef< - TFeatures, - TData, - unknown - > - - column.columns = groupingColumnDef.columns - ? recurseColumns(groupingColumnDef.columns, column, depth + 1) - : [] - - return column - }) - } - - return recurseColumns(table.options.columns) + return table_getAllColumns_recurseColumns( + table, + table.options.columns, + undefined, + 0, + ) } /** diff --git a/packages/table-core/src/features/column-faceting/columnFacetingFeature.utils.ts b/packages/table-core/src/features/column-faceting/columnFacetingFeature.utils.ts index 8c76af0f48..3009cbb502 100644 --- a/packages/table-core/src/features/column-faceting/columnFacetingFeature.utils.ts +++ b/packages/table-core/src/features/column-faceting/columnFacetingFeature.utils.ts @@ -23,10 +23,7 @@ export function column_getFacetedMinMaxValues< column: Column_Internal, table: Table_Internal, ): [number, number] | undefined { - const facetedMinMaxValuesFn = - table.options.features.facetedMinMaxValues?.(table, column.id) ?? - (() => undefined) - return facetedMinMaxValuesFn() + return table.options.features.facetedMinMaxValues?.(table, column.id)?.() } /** @@ -49,10 +46,7 @@ export function column_getFacetedRowModel< column: Column_Internal | undefined, table: Table_Internal, ): RowModel { - const facetedRowModelFn = - table.options.features.facetedRowModel?.(table, column?.id ?? '') ?? - (() => table.getPreFilteredRowModel()) - return facetedRowModelFn() + return table.options.features.facetedRowModel?.(table, column?.id ?? '')?.() ?? table.getPreFilteredRowModel() } /** @@ -74,10 +68,7 @@ export function column_getFacetedUniqueValues< column: Column_Internal, table: Table_Internal, ): Map { - const facetedUniqueValuesFn = - table.options.features.facetedUniqueValues?.(table, column.id) ?? - (() => new Map()) - return facetedUniqueValuesFn() + return table.options.features.facetedUniqueValues?.(table, column.id)?.() ?? new Map() } /** @@ -95,10 +86,7 @@ export function table_getGlobalFacetedMinMaxValues< TFeatures extends TableFeatures, TData extends RowData, >(table: Table_Internal): undefined | [number, number] { - const facetedMinMaxValuesFn = - table.options.features.facetedMinMaxValues?.(table, '__global__') ?? - (() => undefined) - return facetedMinMaxValuesFn() + return table.options.features.facetedMinMaxValues?.(table, '__global__')?.() } /** @@ -117,10 +105,7 @@ export function table_getGlobalFacetedRowModel< TFeatures extends TableFeatures, TData extends RowData, >(table: Table_Internal): RowModel { - const facetedRowModelFn = - table.options.features.facetedRowModel?.(table, '__global__') ?? - (() => table.getPreFilteredRowModel()) - return facetedRowModelFn() + return table.options.features.facetedRowModel?.(table, '__global__')?.() ?? table.getPreFilteredRowModel() } /** @@ -138,8 +123,5 @@ export function table_getGlobalFacetedUniqueValues< TFeatures extends TableFeatures, TData extends RowData, >(table: Table_Internal): Map { - const facetedUniqueValuesFn = - table.options.features.facetedUniqueValues?.(table, '__global__') ?? - (() => new Map()) - return facetedUniqueValuesFn() + return table.options.features.facetedUniqueValues?.(table, '__global__')?.() ?? new Map() } diff --git a/packages/table-core/src/features/column-faceting/createFacetedUniqueValues.ts b/packages/table-core/src/features/column-faceting/createFacetedUniqueValues.ts index 8c6ce5c86e..727d0eb461 100644 --- a/packages/table-core/src/features/column-faceting/createFacetedUniqueValues.ts +++ b/packages/table-core/src/features/column-faceting/createFacetedUniqueValues.ts @@ -51,14 +51,12 @@ function _createFacetedUniqueValues< for (let j = 0; j < values.length; j++) { const value = values[j] - if (facetedUniqueValues.has(value)) { - facetedUniqueValues.set( - value, - (facetedUniqueValues.get(value) ?? 0) + 1, - ) - } else { - facetedUniqueValues.set(value, 1) - } + + const prevValue = facetedUniqueValues.get(value) + facetedUniqueValues.set( + value, + prevValue ? (prevValue + 1) : 1, + ) } } diff --git a/packages/table-core/src/features/row-sorting/createSortedRowModel.ts b/packages/table-core/src/features/row-sorting/createSortedRowModel.ts index 87415c6efd..dbfb441521 100644 --- a/packages/table-core/src/features/row-sorting/createSortedRowModel.ts +++ b/packages/table-core/src/features/row-sorting/createSortedRowModel.ts @@ -1,12 +1,12 @@ import { makeObjectMap, tableMemo } from '../../utils' import { table_autoResetPageIndex } from '../row-pagination/rowPaginationFeature.utils' import { column_getCanSort, column_getSortFn } from './rowSortingFeature.utils' +import type { ColumnSort, SortFn } from './rowSortingFeature.types' import type { Column_Internal } from '../../types/Column' import type { TableFeatures } from '../../types/TableFeatures' import type { RowModel } from '../../core/row-models/coreRowModelsFeature.types' import type { Table, Table_Internal } from '../../types/Table' import type { Row } from '../../types/Row' -import type { SortFn } from './rowSortingFeature.types' import type { RowData } from '../../types/type-utils' /** @@ -50,105 +50,125 @@ function _createSortedRowModel< const sortedFlatRows: Array> = [] - // Filter out sortings that correspond to non existing columns - const availableSorting = sorting.filter((sort) => - column_getCanSort( - table.getColumn(sort.id) as Column_Internal, - ), - ) - const columnInfoById = makeObjectMap<{ sortUndefined?: false | -1 | 1 | 'first' | 'last' invertSorting?: boolean sortFn: SortFn }>() - availableSorting.forEach((sortEntry) => { - const column: Column_Internal | undefined = - table.getColumn(sortEntry.id) - if (!column) return - - columnInfoById[sortEntry.id] = { - sortUndefined: column.columnDef.sortUndefined, - invertSorting: column.columnDef.invertSorting, - sortFn: column_getSortFn(column), + const availableSorting: typeof sorting = [] + for (let i = 0; i < sorting.length; i++) { + const sort = sorting[i]! + + const column = table.getColumn(sort.id) as + | Column_Internal + | undefined + if (column && column_getCanSort(column)) { + availableSorting.push(sort) + columnInfoById[sort.id] = { + sortUndefined: column.columnDef.sortUndefined, + invertSorting: column.columnDef.invertSorting, + sortFn: column_getSortFn(column), + } } - }) + } - const sortData = (rows: Array>) => { - const sortedData = rows.slice() - - sortedData.sort((rowA, rowB) => { - for (let i = 0; i < availableSorting.length; i++) { - const sortEntry = availableSorting[i]! - const columnInfo = columnInfoById[sortEntry.id]! - const sortUndefined = columnInfo.sortUndefined - const isDesc = sortEntry.desc - - let sortInt = 0 - - // All sorting ints should always return in ascending order - if (sortUndefined) { - const aValue = rowA.getValue(sortEntry.id) - const bValue = rowB.getValue(sortEntry.id) - - const aUndefined = aValue === undefined - const bUndefined = bValue === undefined - - if (aUndefined || bUndefined) { - if (sortUndefined === 'first') return aUndefined ? -1 : 1 - if (sortUndefined === 'last') return aUndefined ? 1 : -1 - sortInt = - aUndefined && bUndefined - ? 0 - : aUndefined - ? sortUndefined - : -sortUndefined - } - } + return { + rows: sortData( + preSortedRowModel.rows, + sortedFlatRows, + availableSorting, + columnInfoById, + ), + flatRows: sortedFlatRows, + rowsById: preSortedRowModel.rowsById, + } +} - if (sortInt === 0) { - sortInt = columnInfo.sortFn(rowA, rowB, sortEntry.id) +const sortData = ( + rows: Array>, + sortedFlatRows: Array>, + availableSorting: Array, + columnInfoById: Record< + string, + { + sortUndefined?: false | -1 | 1 | 'first' | 'last' + invertSorting?: boolean + sortFn: SortFn + } + >, +) => { + const sortedData = rows.slice() + + sortedData.sort((rowA, rowB) => { + for (let i = 0; i < availableSorting.length; i++) { + const sortEntry = availableSorting[i]! + const columnInfo = columnInfoById[sortEntry.id]! + const sortUndefined = columnInfo.sortUndefined + const isDesc = sortEntry.desc + + let sortInt = 0 + + // All sorting ints should always return in ascending order + if (sortUndefined) { + const aValue = rowA.getValue(sortEntry.id) + const bValue = rowB.getValue(sortEntry.id) + + const aUndefined = aValue === undefined + const bUndefined = bValue === undefined + + if (aUndefined || bUndefined) { + if (sortUndefined === 'first') return aUndefined ? -1 : 1 + if (sortUndefined === 'last') return aUndefined ? 1 : -1 + sortInt = + aUndefined && bUndefined + ? 0 + : aUndefined + ? sortUndefined + : -sortUndefined } + } - // If sorting is non-zero, take care of desc and inversion - if (sortInt !== 0) { - if (isDesc) { - sortInt *= -1 - } + if (sortInt === 0) { + sortInt = columnInfo.sortFn(rowA, rowB, sortEntry.id) + } - if (columnInfo.invertSorting) { - sortInt *= -1 - } + // If sorting is non-zero, take care of desc and inversion + if (sortInt !== 0) { + if (isDesc) { + sortInt *= -1 + } - return sortInt + if (columnInfo.invertSorting) { + sortInt *= -1 } - } - return rowA.index - rowB.index - }) - // If there are sub-rows, sort them. Clone only rows that need mutation - // (i.e. have subRows) so we don't corrupt the source row model. - for (let i = 0; i < sortedData.length; i++) { - const row = sortedData[i]! - if (row.subRows.length) { - // Preserve prototype chain so methods like getValue() remain accessible - const cloned = Object.create(Object.getPrototypeOf(row)) - Object.assign(cloned, row) - cloned.subRows = sortData(row.subRows) - sortedData[i] = cloned - sortedFlatRows.push(cloned) - } else { - sortedFlatRows.push(row) + return sortInt } } + return rowA.index - rowB.index + }) - return sortedData + // If there are sub-rows, sort them. Clone only rows that need mutation + // (i.e. have subRows) so we don't corrupt the source row model. + for (let i = 0; i < sortedData.length; i++) { + const row = sortedData[i]! + if (row.subRows.length) { + // Preserve prototype chain so methods like getValue() remain accessible + const cloned = Object.create(Object.getPrototypeOf(row)) + Object.assign(cloned, row) + cloned.subRows = sortData( + row.subRows, + sortedFlatRows, + availableSorting, + columnInfoById, + ) + sortedData[i] = cloned + sortedFlatRows.push(cloned) + } else { + sortedFlatRows.push(row) + } } - return { - rows: sortData(preSortedRowModel.rows), - flatRows: sortedFlatRows, - rowsById: preSortedRowModel.rowsById, - } + return sortedData } diff --git a/packages/table-core/src/fns/aggregationFns.ts b/packages/table-core/src/fns/aggregationFns.ts index 457296d35c..ae3e3d38e8 100755 --- a/packages/table-core/src/fns/aggregationFns.ts +++ b/packages/table-core/src/fns/aggregationFns.ts @@ -18,10 +18,12 @@ export function aggregationFn_sum< ) { // It's faster to just add the aggregations together instead of // process leaf nodes individually - return childRows.reduce((sumValue, next) => { - const nextValue = next.getValue(columnId) - return sumValue + (typeof nextValue === 'number' ? nextValue : 0) - }, 0) + let sumValue = 0 + for (let i = 0; i < childRows.length; i++) { + const nextValue = childRows[i]!.getValue(columnId) + if (typeof nextValue === 'number') sumValue += nextValue + } + return sumValue } /** @@ -40,8 +42,8 @@ export function aggregationFn_min< ) { let minValue: number | undefined - childRows.forEach((row) => { - const value = row.getValue(columnId) + for (let i = 0; i < childRows.length; i++) { + const value = childRows[i]!.getValue(columnId) if ( value != null && @@ -50,7 +52,7 @@ export function aggregationFn_min< ) { minValue = value } - }) + } return minValue } @@ -71,8 +73,9 @@ export function aggregationFn_max< ) { let maxValue: number | undefined - childRows.forEach((row) => { - const value = row.getValue(columnId) + for (let i = 0; i < childRows.length; i++) { + const value = childRows[i]!.getValue(columnId) + if ( value != null && typeof value === 'number' && @@ -80,7 +83,7 @@ export function aggregationFn_max< ) { maxValue = value } - }) + } return maxValue } @@ -102,8 +105,8 @@ export function aggregationFn_extent< let minValue: number | undefined let maxValue: number | undefined - childRows.forEach((row) => { - const value = row.getValue(columnId) + for (let i = 0; i < childRows.length; i++) { + const value = childRows[i]!.getValue(columnId) if (value != null && typeof value === 'number') { if (minValue === undefined) { minValue = maxValue = value @@ -112,7 +115,7 @@ export function aggregationFn_extent< if (maxValue! < value) maxValue = value } } - }) + } return [minValue, maxValue] } @@ -130,23 +133,23 @@ export function aggregationFn_mean< let count = 0 let sumValue = 0 - leafRows.forEach((row) => { - const value = row.getValue(columnId) - if (value != null && typeof value === 'number') { - ++count - sumValue += value - } else if (value != null) { - const numValue = +value - if (!Number.isNaN(numValue)) { + for (let i = 0; i < leafRows.length; i++) { + const value = leafRows[i]!.getValue(columnId) + if (value != null) { + if (typeof value === 'number') { ++count - sumValue += numValue + sumValue += value + } else { + const numValue = +value + if (!Number.isNaN(numValue)) { + ++count + sumValue += numValue + } } } - }) + } if (count) return sumValue / count - - return } /** @@ -159,26 +162,26 @@ export function aggregationFn_median< TFeatures extends TableFeatures, TData extends RowData, >(columnId: string, leafRows: Array>) { - if (!leafRows.length) { + const len = leafRows.length + + if (len === 0) { return } + if (len === 1) { + const v = leafRows[0]!.getValue(columnId) + return typeof v === 'number' ? v : undefined + } - const values: Array = new Array(leafRows.length) - for (let i = 0; i < leafRows.length; i++) { + const values: Array = new Array(len) + for (let i = 0; i < len; i++) { const v = leafRows[i]!.getValue(columnId) if (typeof v !== 'number') return values[i] = v } - if (values.length === 1) { - return values[0] - } - - const mid = Math.floor(values.length / 2) + const mid = len >>> 1 // Divide by 2 and floor values.sort((a, b) => a - b) - return values.length % 2 !== 0 - ? values[mid] - : (values[mid - 1]! + values[mid]!) / 2 + return (len & 1) === 1 ? values[mid] : (values[mid - 1]! + values[mid]!) / 2 } /** diff --git a/packages/table-core/src/fns/sortFns.ts b/packages/table-core/src/fns/sortFns.ts index 80cad617dd..cd96315cf5 100644 --- a/packages/table-core/src/fns/sortFns.ts +++ b/packages/table-core/src/fns/sortFns.ts @@ -136,10 +136,7 @@ function compareBasic(a: any, b: any) { function toString(a: any) { if (typeof a === 'number') { - if (isNaN(a) || a === Infinity || a === -Infinity) { - return '' - } - return String(a) + return Number.isFinite(a) ? '' + a : '' } if (typeof a === 'string') { return a diff --git a/packages/table-core/src/utils.ts b/packages/table-core/src/utils.ts index c5d642d2d2..a7b71b4663 100755 --- a/packages/table-core/src/utils.ts +++ b/packages/table-core/src/utils.ts @@ -109,20 +109,15 @@ export function isFunction(d: any): d is T { export function flattenBy( arr: Array, getChildren: (item: TNode) => Array, + flat: Array = [] ) { - const flat: Array = [] - - const recurse = (subArr: Array) => { - subArr.forEach((item) => { - flat.push(item) - const children = getChildren(item) - if (children.length) { - recurse(children) - } - }) - } + for (let i = 0; i < arr.length; i++) { + const item = arr[i]! - recurse(arr) + flat.push(item) + const children = getChildren(item) + children.length && flattenBy(children, getChildren, flat) + } return flat } @@ -157,25 +152,30 @@ export const memo = , TDepArgs, TResult>({ const memoizedFn = (depArgs?: TDepArgs): TResult => { onBeforeCompare?.() const newDeps = memoDeps?.(depArgs) - let depsChanged = !newDeps || newDeps.length !== deps?.length - if (!depsChanged && newDeps) { + + if (!newDeps || newDeps.length !== deps?.length) { + onAfterCompare?.(true) + } else { + let depsChanged = false for (let i = 0; i < newDeps.length; i++) { - if (newDeps[i] !== deps![i]) { + if (newDeps[i] !== deps[i]) { depsChanged = true break } } - } - onAfterCompare?.(depsChanged) - if (!depsChanged) { - return result! + onAfterCompare?.(depsChanged) + if (!depsChanged) return result! } deps = newDeps onBeforeUpdate?.() - result = fn(...(newDeps ?? ([] as any))) + result = deps?.length + ? // @ts-expect-error no correct type for this + fn(...deps) + : // @ts-expect-error no correct type for this + fn() onAfterUpdate?.(result) return result @@ -197,13 +197,7 @@ interface TableMemoOptions< table: Table_Internal } -const pad = (str: number | string, num: number) => { - str = String(str) - while (str.length < num) { - str = ' ' + str - } - return str -} +const noopCallback = () => {} /** * Creates a table-aware memoized function. @@ -232,8 +226,6 @@ export function tableMemo< let debugCache: boolean | undefined if (process.env.NODE_ENV === 'development') { - const { debugCache: _debugCache, debugAll } = table.options - debugCache = _debugCache const { parentName } = getFunctionNameInfo(fnName, '.') const debugByParent = @@ -241,17 +233,16 @@ export function tableMemo< table.options[ `debug${(parentName != 'table' ? parentName + 's' : parentName).replace( parentName, - parentName.charAt(0).toUpperCase() + parentName.slice(1), + parentName[0]!.toUpperCase() + parentName.slice(1), )}` ] const debugByFeature = feature ? // @ts-expect-error - table.options[ - `debug${feature.charAt(0).toUpperCase() + feature.slice(1)}` - ] + table.options[`debug${feature[0]!.toUpperCase() + feature.slice(1)}`] : false - debug = debugAll || debugByParent || debugByFeature + debug = table.options.debugAll || debugByParent || debugByFeature + debugCache = table.options.debugCache } function logTime(time: number, depsChanged: boolean) { @@ -264,7 +255,7 @@ export function tableMemo< runCount++ console.groupCollapsed( - `%c⏱ ${pad(`${time.toFixed(1)} ms`, 12)} %c${runType}%c ${fnName}%c ${objectId ? `(${fnName.split('.')[0]}Id: ${objectId})` : ''}`, + `%c⏱ ${`${time.toFixed(1)} ms`.padStart(12)} %c${runType}%c ${fnName}%c ${objectId ? `(${fnName.split('.')[0]}Id: ${objectId})` : ''}`, `font-size: .6rem; font-weight: bold; ${ depsChanged ? `color: hsl( @@ -284,58 +275,54 @@ export function tableMemo< console.groupEnd() } - const onAfterUpdateHandler = () => { - if (!onAfterUpdate) { - return - } - - const { schedule, untrack } = table._reactivity - schedule(() => untrack(() => onAfterUpdate())) - } + const onAfterUpdateHandler = onAfterUpdate + ? () => { + const { schedule, untrack } = table._reactivity + schedule(() => untrack(() => onAfterUpdate())) + } + : noopCallback - const debugOptions = + const allOptions = process.env.NODE_ENV === 'development' ? { - onBeforeCompare: () => { - if (debugCache) { - beforeCompareTime = performance.now() - } - }, - onAfterCompare: (depsChanged: boolean) => { - if (debugCache) { - afterCompareTime = performance.now() - const compareTime = - Math.round((afterCompareTime - beforeCompareTime) * 100) / 100 - if (!depsChanged) { - logTime(compareTime, depsChanged) + ...memoOptions, + onBeforeCompare: debugCache + ? () => { + beforeCompareTime = performance.now() + } + : noopCallback, + onAfterCompare: debugCache + ? (depsChanged: boolean) => { + afterCompareTime = performance.now() + if (!depsChanged) { + const compareTime = + Math.round((afterCompareTime - beforeCompareTime) * 100) / + 100 + logTime(compareTime, depsChanged) + } + } + : noopCallback, + onBeforeUpdate: debug + ? () => { + startCalcTime = performance.now() + } + : noopCallback, + onAfterUpdate: debug + ? () => { + endCalcTime = performance.now() + const executionTime = + Math.round((endCalcTime - startCalcTime) * 100) / 100 + logTime(executionTime, true) + onAfterUpdateHandler() } - } - }, - onBeforeUpdate: () => { - if (debug) { - startCalcTime = performance.now() - } - }, - onAfterUpdate: () => { - if (debug) { - endCalcTime = performance.now() - const executionTime = - Math.round((endCalcTime - startCalcTime) * 100) / 100 - logTime(executionTime, true) - } - onAfterUpdateHandler() - }, + : onAfterUpdateHandler, } : { - onAfterUpdate: () => { - onAfterUpdateHandler() - }, + ...memoOptions, + onAfterUpdate: onAfterUpdateHandler, } - return memo({ - ...memoOptions, - ...debugOptions, - }) + return memo(allOptions) } export interface API, TDepArgs> {