react-virtualized网格从服务中检索图像,但直到滚动动作才渲染

时间:2019-01-18 20:14:36

标签: javascript reactjs asynchronous react-virtualized

我正在构建一个组件,该组件在反应虚拟化的网格中显示从服务器检索到的数据。除一个问题外,一切工作正常:首次渲染组件时,不显示检索到的图像。但是,一旦发生滚动操作,它们将变为可用。

我认为这与我的Promises的工作方式有关,但我似乎找不到解决方案。

已成功检索图像数据,并使用该数据成功更新了状态,但是仍未显示。

我理解此方法的工作方式是,当使用“ rowRenderer”回调渲染网格中的任何单元格时,应触发“ whenSectionRendered”回调,从而导致以下顺序:

  1. 对“ loadNewImagesBetweenIndices”的调用
  2. 在提供的索引之间的每一行调用“ loadHistImage”
  3. “ loadHistImage”从imageService.retrieveImage函数返回一个承诺,该函数接收base64图像,然后将图像数据作为“ image_decision”放置在我的对象上,并使用新对象调用“ updateSpotHistoryData”。
  4. “ updateSpotHistoryData”更新状态,用新数据替换“ spotHistoryData”状态并触发重新渲染。
  5. 我希望重新渲染后单击“ HistoryImageButton”时可以显示该图像,但是直到发生滚动事件时才显示该图像。这是我的问题。

我尝试了以下操作:

  1. 在“ componentDidMount”和/或“ componentDidUpdate”中调用“ loadNewImagesBetweenIndices”。
  2. 直接在“ rowRenderer”回调中调用“ loadHistImage”。
  3. 再次使用setState强制重新渲染对象。
  4. 从“ whenSectionRendered”功能中删除“ clearImagesBetweenIndicesNotInView”调用。
class HistoryDisplay extends PureComponent{
  constructor(props) {
    super(props);

    this.state = {
      width: 1000,
      previousIdxStart: -1,
      previousIdxStop: -1,
      spotHistoryData: ''
    }

    this.cellRenderer = this.cellRenderer.bind(this);
    this.whenSectionRendered = this.whenSectionRendered.bind(this);
    this.loadHistImage = this.loadHistImage.bind(this);
    this.loadHistory = this.loadHistory.bind(this);
    this.removeHistImages = this.removeHistImages.bind(this);
  }

  componentDidMount() {
    this.resetRowWidthIfRequired();
    this.loadHistory(this.props.spotId);
  } 

  componentDidUpdate(prevProps) {
    this.resetPrevIdxIfRequired(prevProps);
    if(prevProps.spotId !== this.props.spotId){ 
      this.loadHistory(this.props.spotId);
    }
  }

  ...

  async loadHistImage(imageId) {
    return imageService.retrieveImage(imageId)
      .then(data => {
        const newHistData = this.state.spotHistoryData.map(x => {
          if (x.id_image_decision === imageId){
            x.image_decision = data;
          }
          return x;
        });
        this.updateSpotHistoryData(newHistData);
      });

  }

  updateSpotHistoryData(newHistoryData) {
    this.setState({
      spotHistoryData: newHistoryData
    });
  }

  whenSectionRendered({rowOverscanStartIndex, rowOverscanStopIndex}) {
    const { previousIdxStart, previousIdxStop } = this.state;
    this.loadNewImagesBetweenIndices(
      this.state.spotHistoryData, 
      rowOverscanStartIndex, 
      rowOverscanStopIndex);
    this.clearImagesBetweenIndicesNotInView(
      rowOverscanStartIndex,
      rowOverscanStopIndex,
      previousIdxStart, 
      previousIdxStop);
  }

  loadNewImagesBetweenIndices(array, startIdx, stopIdx) {
    for(let rowIndex=startIdx; rowIndex<stopIdx; rowIndex++) {
      this.loadHistImage(array[rowIndex].id_image_decision)
    }
    this.setState({
      previousIdxStart: startIdx,
      previousIdxStop: stopIdx
    });
  }

  cellRenderer({columnIndex, key, rowIndex, style}) {
    const { spotHistoryData } = this.state;
    return(
      <div key={key} >
        {this.createCell(spotHistoryData, columnIndex, rowIndex, style)}
      </div>
    );
  }


  createCell(items, columnIndex, rowIndex, style){
    const formattedTimestamp = (new Date(items[rowIndex].time_stamp_decision)).toLocaleString();
    const btnColor = 'white';
    switch(columnIndex){
      case 0:
        return this.renderHistoryImageButton(
                  this.createCellId(columnIndex, rowIndex), 
                  btnColor, 
                  style, 
                  formattedTimestamp, 
                  items[rowIndex].image_decision
                );
      case 1:
        return this.renderHistoryDataButton(
                  this.createCellId(columnIndex, rowIndex), 
                  btnColor, 
                  style, 
                  'Timestamp', 
                  formattedTimestamp
                );
      ...
    }
  }

  render() {
    const { height, rowHeight } = this.props;
    const { width, spotHistoryData } = this.state;

    return(
      <Col>
        <Grid 
          width={width}
          height={height}
          rowHeight={rowHeight}
          cellRenderer={this.cellRenderer}
          rowCount={spotHistoryData.length} 
          columnCount={7}
          columnWidth={this.getCellWidth}
          estimatedColumnSize={100}
          overscanRowCount={3} 
          overscanColumnCount={3}
          onSectionRendered={this.whenSectionRendered}
          noContentRenderer={this.renderNoContent}
        />
      </Col>
    );
  }
}

我的期望是,一旦诺言返回提供了图像数据并更新了“ spotHistoryData”对象的状态,则将显示不需要附加滚动操作即可显示附加到对象的图像。

0 个答案:

没有答案