2017-11-15 24 views
0

React Virtualized를 사용하여 채팅 응용 프로그램을 만들려고합니다. 지금까지 모든 것이 작동하지만 목록에서 keyMapper와 rowRenderer를 사용할 때 잘못된 생각을하고 있다고 생각합니다.React Virtualized CellMeasurer를 사용하여 목록 및 동적 높이의 데이터 순서 변경하기

캐시는 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; 
}; 

그래서 자신의 인덱스가 변경에도 불구하고, 항목을 재 측정 할 필요가 없습니다.