Skip to content

Commit

Permalink
Added id-based cell size cache
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Vaughn committed Jan 12, 2017
1 parent 9b2f552 commit bd77c3c
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 9 deletions.
5 changes: 4 additions & 1 deletion docs/CellMeasurer.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ class CellSizeCache {
```

The [default caching strategy](https://github.com/bvaughn/react-virtualized/blob/master/source/CellMeasurer/defaultCellSizeCache.js) is exported as `defaultCellMeasurerCellSizeCache` should you wish to decorate it.
You can also use [an alternative caching strategy](https://github.com/bvaughn/react-virtualized/blob/master/source/CellMeasurer/uniformSizeCellSizeCache.js) for lists with a uniform (yet unknown) row height, exported as `uniformSizeCellMeasurerCellSizeCache`.
You can also pass `uniformRowHeight` and/or `uniformColumnWidth` named parameters to the constructor for lists with a uniform (yet unknown) cell sizes.

An [id-based caching strategy](https://github.com/bvaughn/react-virtualized/blob/master/source/CellMeasurer/idCellSizeCache.js) is also available for data that may be sorted.
This strategy maps data ids to cell sizes rathe than index so that the sorting order of the data does not invalidate sizes.

### Examples

Expand Down
14 changes: 7 additions & 7 deletions source/CellMeasurer/defaultCellSizeCache.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Permanently caches all cell sizes (identified by column and row index) unless explicitly cleared.
* Can be configured to handle uniform cell widths and/or heights as a way of optimizing certain use cases.
*/
export default class CellSizeCache {
export default class DefaultCellSizeCache {
constructor ({
uniformRowHeight = false,
uniformColumnWidth = false
Expand All @@ -28,36 +28,36 @@ export default class CellSizeCache {
this._cachedRowHeights = {}
}

clearColumnWidth (index: number) {
clearColumnWidth (index: any) {
this._cachedColumnWidth = undefined

delete this._cachedColumnWidths[index]
}

clearRowHeight (index: number) {
clearRowHeight (index: any) {
this._cachedRowHeight = undefined

delete this._cachedRowHeights[index]
}

getColumnWidth (index: number): ?number {
getColumnWidth (index: any): ?number {
return this._uniformColumnWidth
? this._cachedColumnWidth
: this._cachedColumnWidths[index]
}

getRowHeight (index: number): ?number {
getRowHeight (index: any): ?number {
return this._uniformRowHeight
? this._cachedRowHeight
: this._cachedRowHeights[index]
}

setColumnWidth (index: number, width: number) {
setColumnWidth (index: any, width: number) {
this._cachedColumnWidth = width
this._cachedColumnWidths[index] = width
}

setRowHeight (index: number, height: number) {
setRowHeight (index: any, height: number) {
this._cachedRowHeight = height
this._cachedRowHeights[index] = height
}
Expand Down
72 changes: 72 additions & 0 deletions source/CellMeasurer/idCellSizeCache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/** @flow */
import DefaultCellSizeCache from './defaultCellSizeCache'

type IdCellSizeCacheConstructorParams = {
indexToIdMap : Function,
uniformRowHeight ?: boolean,
uniformColumnWidth ?: boolean
};

/**
* Alternate CellMeasurer `cellSizeCache` implementation.
* Similar to `defaultCellSizeCache` except that sizes are tied to data id rather than index.
* Requires an index-to-id map function (passed in externally) to operate.
*/
export default function idCellSizeCache ({
indexToIdMap,
uniformColumnWidth = false,
uniformRowHeight = false
} : IdCellSizeCacheConstructorParams) {
const cellSizeCache = new DefaultCellSizeCache({
uniformColumnWidth,
uniformRowHeight
})

return {
clearAllColumnWidths () {
cellSizeCache.clearAllColumnWidths()
},

clearAllRowHeights () {
cellSizeCache.clearAllRowHeights()
},

clearColumnWidth (index: number) {
cellSizeCache.clearColumnWidth(
indexToIdMap(index)
)
},

clearRowHeight (index: number) {
cellSizeCache.clearRowHeight(
indexToIdMap(index)
)
},

getColumnWidth (index: number): ?number {
return cellSizeCache.getColumnWidth(
indexToIdMap(index)
)
},

getRowHeight (index: number): ?number {
return cellSizeCache.getRowHeight(
indexToIdMap(index)
)
},

setColumnWidth (index: number, width: number) {
cellSizeCache.setColumnWidth(
indexToIdMap(index),
width
)
},

setRowHeight (index: number, height: number) {
cellSizeCache.setRowHeight(
indexToIdMap(index),
height
)
}
}
}
68 changes: 68 additions & 0 deletions source/CellMeasurer/idCellSizeCache.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import idCellSizeCache from './idCellSizeCache'

describe('idCellSizeCache', () => {
it('should track width and height using id instead of index', () => {
const indexToIdMap = {
0: 'foo',
1: 'bar',
2: 'baz'
}
const indexToIdMapCalls = []
const cache = idCellSizeCache({
indexToIdMap: (index) => {
indexToIdMapCalls.push(index)
return indexToIdMap[index]
}
})

// Set values with initial indices
cache.setColumnWidth(0, 100)
cache.setRowHeight(0, 25)
cache.setColumnWidth(1, 200)
cache.setRowHeight(1, 50)
cache.setColumnWidth(2, 300)
cache.setRowHeight(2, 75)

// Mimic a sort operation
indexToIdMap[0] = 'baz'
indexToIdMap[1] = 'bar'
indexToIdMap[2] = 'foo'

// Previous widths and heights should still be available
expect(cache.getColumnWidth(0)).toBe(300)
expect(cache.getRowHeight(0)).toBe(75)
expect(cache.getColumnWidth(1)).toBe(200)
expect(cache.getRowHeight(1)).toBe(50)
expect(cache.getColumnWidth(2)).toBe(100)
expect(cache.getRowHeight(2)).toBe(25)

// Clear a specific item
cache.clearColumnWidth(0)
cache.clearRowHeight(0)

// Mimic a sort operation
indexToIdMap[0] = 'bar'
indexToIdMap[1] = 'foo'
indexToIdMap[2] = 'baz'

// Previous widths and heights should still be available
expect(cache.getColumnWidth(0)).toBe(200)
expect(cache.getRowHeight(0)).toBe(50)
expect(cache.getColumnWidth(1)).toBe(100)
expect(cache.getRowHeight(1)).toBe(25)
expect(cache.getColumnWidth(2)).toBeUndefined()
expect(cache.getRowHeight(2)).toBeUndefined()

// Clear all items
cache.clearAllColumnWidths()
cache.clearAllRowHeights()

// No sizes should be available
expect(cache.getColumnWidth(0)).toBeUndefined()
expect(cache.getRowHeight(0)).toBeUndefined()
expect(cache.getColumnWidth(1)).toBeUndefined()
expect(cache.getRowHeight(1)).toBeUndefined()
expect(cache.getColumnWidth(2)).toBeUndefined()
expect(cache.getRowHeight(2)).toBeUndefined()
})
})
1 change: 1 addition & 0 deletions source/CellMeasurer/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export default from './CellMeasurer'
export CellMeasurer from './CellMeasurer'
export defaultCellSizeCache from './defaultCellSizeCache'
export idCellSizeCache from './idCellSizeCache'
3 changes: 2 additions & 1 deletion source/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ export { AutoSizer } from './AutoSizer'
export {
CellMeasurer,
defaultCellSizeCache as defaultCellMeasurerCellSizeCache,
defaultCellSizeCache as uniformSizeCellMeasurerCellSizeCache // 7.21 backwards compatible export
defaultCellSizeCache as uniformSizeCellMeasurerCellSizeCache, // 7.21 backwards compatible export
idCellSizeCache as idCellMeasurerCellSizeCache
} from './CellMeasurer'
export { Collection } from './Collection'
export { ColumnSizer } from './ColumnSizer'
Expand Down

0 comments on commit bd77c3c

Please sign in to comment.