有没有办法使用react-virtualized实现动态高度的网格标题?

时间:2017-11-25 18:01:37

标签: reactjs react-virtualized

我正在开发基于反应虚拟化的数据网格组件。它应该有一个带有可调整大小的列的固定标题。我希望标题根据标题单元格内容更改其高度。我使用CellMeasurer计算单元格高度并更新标题的高度。

问题是在渲染单元格之后计算单元格大小(afaik),因此如果高度已更改,我必须在标题forceUpdate内调用render。 / p>

以下是render的样子(完整示例为here):

render() {
    const height = this._cache.rowHeight({ index: 0 });
    console.log('render', height, this.props.sizes);
    setTimeout(() => {
      if (height !== this._cache.rowHeight({ index: 0 })) {
        console.log('forceUpdate', this._cache.rowHeight({ index: 0 }))
        this.forceUpdate()
      }
    }, 0)

    return (
      <Grid 
        ref={ref => this._grid = ref}
        deferredMeasurementCache={this._cache}
        width={1500}
        height={height}
        columnCount={5}
        columnWidth={this.columnWidth}
        rowCount={1}
        rowHeight={this._cache.rowHeight}
        cellRenderer={this.renderCell}
      />
    );
  }

所以问题是如何避免forceUpdate?有没有更简洁的方法使用react-virtualized来实现具有动态高度的网格标题?

1 个答案:

答案 0 :(得分:2)

render中设置超时可能不是一个好主意。

如果单元格的高度发生变化(例如从rowHeight返回的值),则CellMeasurer will automatically notify the parent Grid。在这种情况下,Grid will automatically clear its position cache and re-render

在此示例中,您正在做的不同之处是将Grid的外部高度设置为等于单元格测量的高度。这不是一个常见的用例,但是你可以支持它而不需要像这样的计时器 - 黑客:

class XHeader extends React.Component {
  _cache = new CellMeasurerCache({
    defaultHeight: 20,
    fixedWidth: true,
  });
  state = {
    headerHeight: 20,
  };
  renderCell = props => {
    return (
      <HeaderCell 
        width={this.props.sizes[props.columnIndex]}
        {...props}
        cache={this._cache}
        onMouseDown={this.props.onMouseDown}
      />
    );
  }
  columnWidth = ({ index }) => {
    return this.props.sizes[index];
  }
  render() {
    return (
      <Grid 
        ref={ref => this._grid = ref}
        deferredMeasurementCache={this._cache}
        width={1500}
        height={this.state.headerHeight}
        columnCount={5}
        columnWidth={this.columnWidth}
        onSectionRendered={this._onSectionRendered}
        rowCount={1}
        rowHeight={this._cache.rowHeight}
        cellRenderer={this.renderCell}
      />
    );
  }

  _onSectionRendered = ({ rowOverscanStartIndex }) => {
    if (rowOverscanStartIndex === 0) {
      const height = this._cache.rowHeight({ index: 0 });

      if (height !== this.state.headerHeight) {
        this.setState({
          headerHeight: height,
        });
      }
    }
  }
}