2017-11-15 14 views
0

React Virtualizedを使用してチャットアプリケーションを作成しようとしています。これまでのところすべてが機能していますが、リストからkeyMapperとrowRendererを使用するときに何か間違っていると思います。React Virtualized CellMeasurerをListおよびDynamic Heightのデータ順序を変更して使用する

キャッシュはIDを使用して_rowHeightCacheに高さを格納していますが、高さはIDではなくインデックスを使用して検索されるようです。右の高さやその性質を得るために、idをrowIndexとしてCellMeasurerに渡す必要があるかどうかはわかりません。

問題は、メッセージリストの順序が変更されているために高さが正しくないため、インデックスの高さが適切ではなく、メッセージを削除してインデックスオーダーを乱すことがあるということです。これは、高さを調べるためにkeyMapperを使って修正する必要があると思いますが、間違っている必要があります。

以下は、私がどのように使用しているのか編集されたダウンバージョンです。

constructor(props) { 
     this._cache = new CellMeasurerCache({ 
      defaultHeight: 45, 
      fixedWidth: true, 
      keyMapper: (index) => _.get(this.props.messageList[index], ['msgId']) 
     }); 
    } 

    render() { 
     const props = this.filterProps(this.props), 
      list = this.props.messageList, 
      rowCount = list.length; 

     return (

      <InfiniteLoader 
       threshold={0} 
       isRowLoaded={this._isRowLoaded} 
       loadMoreRows={this._loadMoreRows} 
       rowCount={rowCount}> 
       {({onRowsRendered, registerChild}) => (
        <AutoSizer> 
         {({width, height}) => (
          <List 
           ref={(ref) => { 
            this.streamLane = ref; 
            registerChild(ref); 
           }} 
           height={height} 
           width={width} 
           onRowsRendered={onRowsRendered} 
           rowCount={rowCount} 
           rowRenderer={this._rowRenderer} 
           deferredMeasurementCache={this._cache} 
           rowHeight={this._cache.rowHeight} 
          /> 
         )} 
        </AutoSizer> 
       )} 
      </InfiniteLoader> 
     ); 
    } 

    _rowRenderer({ index, key, parent, style }) { 
     return (
      <CellMeasurer 
       cache={this._cache} 
       columnIndex={0} 
       key={key} 
       parent={parent} 
       rowIndex={index}> 
       <div style={{...style}}> 
        {this.props.messageList[index]} 
       </div> 
      </CellMeasurer> 
     ); 
    } 

    _loadMoreRows({startIndex, stopIndex}) { 

     return new Promise((resolve) => { 
      if (!!stopIndex || !!startIndex || this.props.hasLastMessage || this.state.isPinned) { 
       return resolve(); 
      } 

      this.props.loadOlder(() => resolve); 
     }); 
    } 

    _isRowLoaded({index}) { 
     if (index === 0) return false; 
     return !!this.props.messageList[index]; 
    } 
    } 

ご意見、ご提案、批判は驚くべきものです。

+0

@brianvaughnあなたがこの記事にあなたにタグを付ける価値があるかもしれないと誰かが言いましたことをお詫びして申し訳ありません。あなたに時間がないなら心配しないでください。ありがとう! – ReganPerkins

答えて

0

問題は、メッセージリストの順序が変更されているために高さが正しくないため、インデックスの高さが適切ではなく、メッセージを削除してインデックスオーダーを乱す可能性があるということです。

あなたのサンプルコードでは、注文がどのように変化するのか、変更後に何をするのかが示されていないので、間違っているとは言い難いです。

しかし、注文が変更されたとき(たとえば、データを並べ替える、または古い項目をシフトさせる新しい項目をリストの先頭に追加する場合)、キャッシュされた位置が古くなる可能性があることをListに知らせる必要があります。あなたのケースでこれを行う場合は、this.streamLane.recomputeRowHeights()に電話する必要があります。

(私はあなたのコードのすべてを持っていないので、あなたがrecomputeRowHeightsに最初に変更されたアイテムのインデックスを渡すことができますが、私は多分すべてのアイテムがシフトしているあなたのケースで想定する?私は、知りません。)

recomputeRowHeightsを呼び出した後、Listは、報告された高さをCellMeasurerCacheで再計算します。 That cache uses your keyMapper function

rowHeight = ({index}: IndexParam) => { 
    const key = this._keyMapper(index, 0); 

    return this._rowHeightCache.hasOwnProperty(key) 
    ? this._rowHeightCache[key] 
    : this._defaultHeight; 
}; 

だから、彼らのインデックスが変更されているにもかかわらず、アイテムを再測定する必要はありません。

関連する問題