-
Notifications
You must be signed in to change notification settings - Fork 164
feat: add support for dynamic row height #170
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
Conversation
Thanks for your contribution, that's a great feature, I have some questions before I take some time for a detailed review
|
@nihgwu Hi, yes it does currently work w/ frozen columns as well as frozen rows. LeftGrid, RightGrid, and MainGrid each call |
@nihgwu As far as using |
src/BaseTable.js
Outdated
@@ -315,7 +316,10 @@ class BaseTable extends React.PureComponent { | |||
? dataGetter({ columns, column, columnIndex, rowData, rowIndex }) | |||
: getValue(rowData, dataKey); | |||
const cellProps = { isScrolling, cellData, columns, column, columnIndex, rowData, rowIndex, container: this }; | |||
const cell = renderElement(cellRenderer || <TableCell className={this._prefixClass('row-cell-text')} />, cellProps); | |||
const cellClasses = cn(this._prefixClass('row-cell-text'), { | |||
[this._prefixClass('row-cell-text-dynamic')]: this.props.useDynamicRowHeight, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the dynamic should be promoted to the row(row--dynamic
) and use :not(.row--dynamic) { .cell-text{} }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps we should promote even further to the top level like table--dynamic
, as all the rows would have the same row--dynamic
className
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking maybe only applying row-cell-text
when not in dynamic mode. None of those properties have any affect when content is dynamically sized, so always adding them and overriding is un-necessary work.
src/BaseTable.js
Outdated
@@ -445,8 +449,22 @@ class BaseTable extends React.PureComponent { | |||
); | |||
} | |||
|
|||
setRowHeight = (index, size) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't use arrow functions in a class component
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you considered about expansion? The indices would change on expand/collapse
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Expansion seems to have fine performance for me locally. I can update this to not use arrow functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think i see what you were alluding to w/ expansion. It seems its not entirely correct. I'll dig into fixing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can use rowKey
as the key instead of index
, as you can have totally different data with the same index
src/BaseTable.js
Outdated
|
||
if (rowHeightMap.hasOwnProperty(index)) { | ||
if (size > rowHeightMap[index]) { | ||
rowHeightMap[index] = size; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you are using index
as the key, why not use an array directly?
also you should use {...map, [index]: size}
to mutate the ref
and if there is no need to re-render, you don't need to always setState at the bottom
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't use an array bc of how rowIndex
is negative for frozen rows. It seemed simpler to pass props.rowIndex
directly through instead of adding logic to figure out original index.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, I totally forget that 👍
Yes in the next major version I will use hooks, but for this version we should try to avoid breaking changes |
For the context, I remember there is a compatible package there? |
Perhaps. I haven't used any but I can check to see if one exists. |
I haven't check if we do need the new context, but here is the polyfill for it https://github.com/jamiebuilds/create-react-context |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job, thanks
src/BaseTable.js
Outdated
@@ -1168,6 +1204,7 @@ BaseTable.propTypes = { | |||
ExpandIcon: PropTypes.func, | |||
SortIndicator: PropTypes.func, | |||
}), | |||
useDynamicRowHeight: PropTypes.bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we could use estimatedRowHeight
for initial height and scrollToRow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if this value is presented, we use VariableSizeGrid
and ignore rowHeight
src/BaseTable.js
Outdated
@@ -473,14 +499,18 @@ class BaseTable extends React.PureComponent { | |||
rowRenderer={this.renderRow} | |||
onScroll={this._handleScroll} | |||
onRowsRendered={this._handleRowsRendered} | |||
useDynamicRowHeight={useDynamicRowHeight} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can use rowHeight: func|number
here, then we don't need to pass so many extra props
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think rowHeight
should become optional then? If user provides number or func, we use that otherwise it's internally calculated using the TableRow.getBoundingClientRect().height
that I added?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's not the same case, for the BaseTable
, the rowHeight
could be optional as there is a default value, so actually we can remove the isRequired
in the propTypes definition without breaking anything, and if we provide estimatedRowHeight
we will ignore rowHeight
and use estimatedRowHeight
instead
for the GridTable
, we use rowHeight: number
as before, but rowHeight: func
in dynamic mode, like rowHeight = index => rowHeightMap[index]
, in this way we don't need to change the props interface at all
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I think i'm following. I'll push an update and see if we're on same page.
For get to mention that if you have tested with the infinite loading feature, I think we can use the innerRef to get the totalRowHeight instead of calculate from the count and rowHeight https://github.com/Autodesk/react-base-table/blob/master/src/BaseTable.js#L150, in that way I think we can make that feature works |
@jamesonhill I just pushed another commit, now you can reset cache without losing performance on resizing, it looks much better now |
I haven't been able to track down what's causing it yet, but i'm seeing a little bit of "weird-ness" the first time I hover over a row (using dynamic heights). It gets smaller while hovering, then goes back to the correct size |
@jamesonhill I've noticed that problem too, will inspect it |
@jamesonhill I've tracked down the issue, but just don't know why ;(, when you hover on a row the first time, the |
@nihgwu yea, that is odd. I'm debugging it and it even looks like they are the same unless i'm missing something. |
Oh, nevermind. It looks like first render is using the estimatedRowHeight values, which makes sense. |
@jamesonhill the object value is the same but the reference is different before/after reset cache |
@jamesonhill I've fixed the issue, and I think it's ready to be merged, please help to review the code I changed, thanks |
@nihgwu it looks good to me. I've done some local testing and don't see the hover issue anymore. Scrolling w/ dynamic row heights is quite fast too! I think it's ready to merge. |
@jamesonhill Cool, let's land it, thank you so much 🎉 |
Awesome, thanks for your assistance & guidance. This should only require a minor version bump to the npm package? |
sure, I'm experimenting with List instead of Grid, if it's a easy switch I want to include it, or I'll release a new version soon |
v1.10.0 is released, I've make List work but it requires api change on |
@jamesonhill I noticed an issue regarding the out sync of measurement in productionhttps://autodesk.github.io/react-base-table/examples/dynamic-row-heights, I guess it's caused by the fact that it's much faster in production that debounce of |
hmm, I'm actually seeing it locally but not in that production example. |
LOL, that's interesting, I'm trying to fix it now |
This adds a new prop
estimatedRowHeight
, which updates the Grid component to useVariableSizeGrid
fromreact-window
instead ofFixedSizeGrid
. WhenestimatedRowHeight
is provided,rowHeight
is ignored and content is dynamically sized.estimatedRowHeight
is used as the default height while measuring the content.