Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create new reusable id-based cache for CellMeasurer #491

Closed
bvaughn opened this issue Dec 4, 2016 · 6 comments
Closed

Create new reusable id-based cache for CellMeasurer #491

bvaughn opened this issue Dec 4, 2016 · 6 comments

Comments

@bvaughn
Copy link
Owner

bvaughn commented Dec 4, 2016

The default cache for CellMeasurer currently stores sizes using indices. It should be possible to store these values using (data) ids instead so that changes to the underlying data (eg sorting, new rows appended) wouldn't invalidate the cached sizes. This would be useful for things like reverse-ordered lists (eg chat).

cc @zsherman

@clauderic
Copy link
Contributor

+1

Ran into the need for this myself a few weeks back (as described in a side-note on #443). This can be a source of perf issues on low powered devices when sorting large lists of complex items (since they need to be re-measured every time).

@zsherman
Copy link

zsherman commented Dec 5, 2016

Yep, we're using this strategy right now without CellMeasurer, just using our own cache and passing heights straight to List. Having this baked in would be awesome though...

@bvaughn
Copy link
Owner Author

bvaughn commented Dec 5, 2016

If you're able, share your impl here @zsherman. I can use it as a starting point (or perhaps use it as-is).

@arusakov
Copy link
Contributor

arusakov commented Dec 5, 2016

👍
@bvaughn I can help you with it too. In my application I already create this kind cache.

Maybe the time is come - we need to create epic issue for official and full featured react-virtualized chat example (with rows appended to top, scroll position saving and so on). There are a lot of chat developers I think.

@bvaughn
Copy link
Owner Author

bvaughn commented Dec 5, 2016

The more the merrier, yeah.

Tempted to say we should hold off on the chat application example until I've had a chance to finish tackling #396 as I think it will address performance problems that come with reverse display and hopefully simplify the process a bit. But I don't know when I'll finish that, so...yeah, maybe we should do it now and just update the example later. 😁 I'd welcome such an example to the site/docs.

@m0xx
Copy link

m0xx commented Dec 16, 2016

I had some performance issue with the CellMeasurer for highly dynamic row height. So i've come up with a simple solution(key based caching) that seemed to resolve also this issue.

I wanted to use the CellMeasurer to calculate the dynamic height but only when a similar row hasn't been computed yet. For example let's say that each row has 0..n child I could use the child count as my key and still benefits from the CellMeasurer to measure all my item + padding/margin.

If someone is interested here is my implementation:

export default class KeyBasedCellSizeCache {
  constructor ({
      buildColumnKey = (index) => (0),
      buildRowKey = (index) => (0)
    } = {}) {
    this._buildColumnKey = buildColumnKey;
    this._buildRowKey = buildRowKey;

    this._keyByRowIndex = {}
    this._keyByColumnIndex = {}

    this._heightByRowKey = {}
    this._widthByColKey = {}
  }

  clearAllColumnWidths () {
    this._keyByRowIndex = {}
  }

  clearAllRowHeights () {
    this._keyByRowIndex = {}
  }

  clearColumnWidth (index) {
    delete this._keyByColumnIndex[index]
  }

  clearRowHeight (index) {
    delete this._keyByRowIndex[index]
  }

  getColumnWidth (index) {
    return this._widthByColKey[this.getColumnKey(index)]
  }

  getRowHeight (index) {
    return this._heightByRowKey[this.getRowKey(index)]
  }

  setColumnWidth (index, width) {
    this._widthByColKey[this.getColumnKey(index)] = width
  }

  setRowHeight (index, height) {
    this._heightByRowKey[this.getRowKey(index)] = height
  }

  getRowKey(index) {
    if(!this._keyByRowIndex[index]) {
      this._keyByRowIndex[index] = this._buildRowKey(index)
    }

    return this._keyByRowIndex[index]
  }

  getColumnKey(index) {
    if(!this._keyByColumnIndex[index]) {
      this._keyByColumnIndex[index] = this._buildColumnKey(index)
    }

    return this._keyByColumnIndex[index]
  }
}

And thanks for this awesome library!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants