Open aybmab opened 8 years ago
I am interetested in this as well. This seems to be a similar discussion - https://github.com/facebook/fixed-data-table/issues/322 - but it doesn't have any answers yet.
Posting this here because it seems to be the most general issue surrounding custom row height.
Using ideas from react-measure
and a custom prop on the Table
called flexibleRows
, I got quite far creating a grid with completely variable rowHeight
measured from the row's own contents.
The initial table looks great but I got stuck when I realised FDT is reusing elements/not rendering rows outside of the viewport/some other magic! - so to measure rows again when they have new contents I've either got to force an update when you scroll or measure every time the cell updates with componentDidUpdate
- either way is really laggy.
Any advice on this would be really welcome, as it's a lot of work for nothing, even though in the end having to implement this feature is very avoidable and I'm probably going to skip having dynamic content in my tables.
handleCellMeasure(rowIndex, dimensions) {
let rowHeights = this.state.rowHeights;
// Only store the largest cell height of a row
if(typeof rowHeights[rowIndex] == 'undefined' || rowHeights[rowIndex] < dimensions.height) {
rowHeights[rowIndex] = dimensions.height;
this.setState({
rowHeights: rowHeights
});
}
}
Any time the grid asks for a row height, check if we've stored it's measurements in state
rowHeightGetter(index) {
let rowHeight = 37; // Set the default rowHeight
if(this.props.flexibleRows) {
let calculatedHeight = this.state.rowHeights[index]; // Retreive the rowHeight stored in state
if(typeof calculatedHeight != 'undefined') {
rowHeight = calculatedHeight + 16; // 8px padding
}
}
return rowHeight;
}
Then in the render of my Grid I am pushing my custom props into FDT components and I wrap the contents cell in a Measuring component.
<Table ...>
{React.Children.map(this.props.children, el => {
if(flexibleRows) {
clonedCell = React.createElement(MeasureCell, {
onMeasure: this.handleCellMeasure.bind(this)
}, clonedCell);
}
// Many more extensions on the column and the header
return React.createElement(Column, {
...props, // Props to pass through to the real column (injecting the data, also - which is neat)
cell: clonedCell,
header: headerCell
});
})}
</Table>
The measure cell is just a component that wraps the cell and measures the height of the element.
// Find the cell contents and measure it
const dimensions = this._node.querySelector('.public_fixedDataTableCell_cellContent').getBoundingClientRect();
if(dimensions.height > 0) {
this.props.onMeasure(this.props.rowIndex, dimensions); // Run the callback function seen above
}
Are there any suggestions on how to go about creating a rowHeightGetter function?