diff --git a/CHANGELOG.md b/CHANGELOG.md
index 18684147..e66046a5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,8 @@
## NEXT VERSION
+- feat: add the ability to pass function in `estimatedRowHeight` to determine the initial height of rows
+
## v1.11.3 (2020-08-24)
- fix: remove propTypes for Column.key
diff --git a/src/BaseTable.js b/src/BaseTable.js
index 54a39f3c..12a35143 100644
--- a/src/BaseTable.js
+++ b/src/BaseTable.js
@@ -19,6 +19,7 @@ import {
renderElement,
normalizeColumns,
getScrollbarSize as defaultGetScrollbarSize,
+ getEstimatedTotalRowsHeight,
isObjectEqual,
callOrReturn,
hasChildren,
@@ -120,6 +121,7 @@ class BaseTable extends React.PureComponent {
this._mainRowHeightMap = {};
this._leftRowHeightMap = {};
this._rightRowHeightMap = {};
+ this._getEstimatedTotalRowsHeight = memoize(getEstimatedTotalRowsHeight);
this._getRowHeight = this._getRowHeight.bind(this);
this._updateRowHeights = debounce(() => {
this._isResetting = true;
@@ -185,7 +187,9 @@ class BaseTable extends React.PureComponent {
const { rowHeight, estimatedRowHeight } = this.props;
if (estimatedRowHeight) {
- return this.table ? this.table.getTotalRowsHeight() : this._data.length * estimatedRowHeight;
+ return this.table
+ ? this.table.getTotalRowsHeight()
+ : this._getEstimatedTotalRowsHeight(this._data, estimatedRowHeight);
}
return this._data.length * rowHeight;
}
@@ -716,7 +720,7 @@ class BaseTable extends React.PureComponent {
[`${classPrefix}--has-frozen-rows`]: frozenData.length > 0,
[`${classPrefix}--has-frozen-columns`]: this.columnManager.hasFrozenColumns(),
[`${classPrefix}--disabled`]: disabled,
- [`${classPrefix}--dynamic`]: estimatedRowHeight > 0,
+ [`${classPrefix}--dynamic`]: !!estimatedRowHeight,
});
return (
@@ -785,7 +789,10 @@ class BaseTable extends React.PureComponent {
// for dynamic row height
_getRowHeight(rowIndex) {
const { estimatedRowHeight, rowKey } = this.props;
- return this._rowHeightMap[this._data[rowIndex][rowKey]] || estimatedRowHeight;
+ return (
+ this._rowHeightMap[this._data[rowIndex][rowKey]] ||
+ callOrReturn(estimatedRowHeight, { rowData: this._data[rowIndex], rowIndex })
+ );
}
_getIsResetting() {
@@ -1103,8 +1110,9 @@ BaseTable.propTypes = {
rowHeight: PropTypes.number,
/**
* Estimated row height, the real height will be measure dynamically according to the content
+ * The callback is of the shape of `({ rowData, rowIndex }) => number`
*/
- estimatedRowHeight: PropTypes.number,
+ estimatedRowHeight: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),
/**
* The height of the table header, set to 0 to hide the header, could be an array to render multi headers.
*/
diff --git a/src/GridTable.js b/src/GridTable.js
index a0216b78..b23ec257 100644
--- a/src/GridTable.js
+++ b/src/GridTable.js
@@ -5,6 +5,7 @@ import { FixedSizeGrid, VariableSizeGrid } from 'react-window';
import memoize from 'memoize-one';
import Header from './TableHeader';
+import { getEstimatedTotalRowsHeight } from './utils';
/**
* A wrapper of the Grid for internal only
@@ -23,6 +24,7 @@ class GridTable extends React.PureComponent {
if (!this.props.estimatedRowHeight) return;
this.bodyRef && this.bodyRef.resetAfterColumnIndex(0, false);
});
+ this._getEstimatedTotalRowsHeight = memoize(getEstimatedTotalRowsHeight);
this.renderRow = this.renderRow.bind(this);
}
@@ -59,7 +61,9 @@ class GridTable extends React.PureComponent {
const { data, rowHeight, estimatedRowHeight } = this.props;
if (estimatedRowHeight) {
- return (this.innerRef && this.innerRef.clientHeight) || data.length * estimatedRowHeight;
+ return (
+ (this.innerRef && this.innerRef.clientHeight) || this._getEstimatedTotalRowsHeight(data, estimatedRowHeight)
+ );
}
return data.length * rowHeight;
}
@@ -114,7 +118,7 @@ class GridTable extends React.PureComponent {
width={width}
height={Math.max(height - headerHeight - frozenRowsHeight, 0)}
rowHeight={estimatedRowHeight ? getRowHeight : rowHeight}
- estimatedRowHeight={estimatedRowHeight}
+ estimatedRowHeight={typeof estimatedRowHeight === 'function' ? undefined : estimatedRowHeight}
rowCount={data.length}
overscanRowCount={overscanRowCount}
columnWidth={estimatedRowHeight ? this._getBodyWidth : bodyWidth}
@@ -198,7 +202,7 @@ GridTable.propTypes = {
headerWidth: PropTypes.number.isRequired,
bodyWidth: PropTypes.number.isRequired,
rowHeight: PropTypes.number.isRequired,
- estimatedRowHeight: PropTypes.number,
+ estimatedRowHeight: PropTypes.oneOfType([PropTypes.func, PropTypes.number]),
getRowHeight: PropTypes.func,
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
data: PropTypes.array.isRequired,
diff --git a/src/TableRow.js b/src/TableRow.js
index d7d44402..be5e8ff0 100644
--- a/src/TableRow.js
+++ b/src/TableRow.js
@@ -183,7 +183,7 @@ TableRow.propTypes = {
rowRenderer: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
cellRenderer: PropTypes.func,
expandIconRenderer: PropTypes.func,
- estimatedRowHeight: PropTypes.number,
+ estimatedRowHeight: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),
getIsResetting: PropTypes.func,
onRowHover: PropTypes.func,
onRowExpand: PropTypes.func,
diff --git a/src/utils.js b/src/utils.js
index 0d98b19a..94cacc6e 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -251,3 +251,9 @@ export function removeClassName(el, className) {
el.className = el.className.replace(new RegExp(`(?:^|\\s)${className}(?!\\S)`, 'g'), '');
}
}
+
+export function getEstimatedTotalRowsHeight(data, estimatedRowHeight) {
+ return typeof estimatedRowHeight === 'function'
+ ? data.reduce((height, rowData, rowIndex) => height + estimatedRowHeight({ rowData, rowIndex }), 0)
+ : data.length * estimatedRowHeight;
+}
diff --git a/types/index.d.ts b/types/index.d.ts
index 1248ad51..bbadb93f 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -208,8 +208,15 @@ declare module 'react-base-table' {
rowHeight?: number;
/**
* Estimated row height, the real height will be measure dynamically according to the content
+ * The callback is of the shape of `({ rowData, rowIndex }) => number`
*/
- estimatedRowHeight?: number;
+ estimatedRowHeight?: CallOrReturn<
+ number,
+ {
+ rowData: T;
+ rowIndex: number;
+ }
+ >;
/**
* The height of the table header, set to 0 to hide the header, could be an array to render multi headers.
*/