2016-12-30 4 views
3

Я прошел много ответов на StackOverflow. Я также просмотрел здесь документ List, react-virtualized/List. Но, тем не менее, я не могу понять, как динамически установить высоту строки в active-virtualized List. Как рассчитать высоту в функции rowHeight?Как настроить динамическую высоту строки в интерактивном виртуализированном списке?

Я могу назвать свою функцию, как rowHeight={({ index }) => this.computeRowHeight({ index })}. Но как вычислить высоту строки?

Ниже приведен код ссылки.

import React, { Component } from 'react'; 
import ReactDOM from 'react-dom'; 
import { AutoSizer, InfiniteLoader, List } from 'react-virtualized'; 
import _ from 'lodash'; 

class InfiniteList extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     list: props.list, 
     loading: false 
    }; 
    } 
    componentDidMount() { 
    fetch('http://jsonplaceholder.typicode.com/comments') 
     .then((response) => { 
     response.json().then((data) => { 
      this.setState({ 
      list: _.concat(this.state.list, _.map(data, 'body')), 
      loading: false 
      }); 
     }); 
     }); 
    } 
    isRowLoaded({ index }) { 
    return !!this.state.list[index]; 
    } 

    loadMoreRows({ startIndex, stopIndex }) { 
    if (this.state.loading) { 
     return; 
    } 
    this.setState({ 
     loading: true 
    }); 
    return fetch('http://jsonplaceholder.typicode.com/comments') 
     .then((response) => { 
     response.json().then((data) => { 
      // Simulate delay 
      setTimeout(() => { 
      this.setState({ 
       list: _.concat(this.state.list, _.map(data, 'body')), 
       loading: false 
      }); 
      }, 3000); 
     }); 
     }); 
    } 

    rowRenderer({ key, index, isScrolling, isVisible, style }) { 
    if (isVisible) { 
     return (
     <div key={key}> 
      <div style={style}>#{this.state.list[index]}.</div> 
     </div> 
    ); 
    } 
    } 

    render() { 
    return (
     <div> 
     <InfiniteLoader 
      isRowLoaded={({ index }) => this.isRowLoaded({ index })} 
      loadMoreRows={({ startIndex, stopIndex }) => this.loadMoreRows({ startIndex, stopIndex })} 
      rowCount={this.state.list.length} 
     > 
      {({ onRowsRendered, registerChild }) => (
      <AutoSizer disableHeight> 
       {({ width }) => (
       <List 
        onRowsRendered={onRowsRendered} 
        ref={registerChild} 
        width={width} 
        height={320} 
        rowCount={this.state.list.length} 
        rowHeight={40} 
        rowRenderer={({ key, index, isScrolling, isVisible, style }) => this.rowRenderer({ key, index, isScrolling, isVisible, style })} 
       /> 
      )} 
      </AutoSizer> 
     )} 
     </InfiniteLoader> 
     {this.state.loading && <p>Loading...</p>} 
     </div> 
    ); 
    } 
} 

const list = []; 

ReactDOM.render(
    <InfiniteList list={list} />, 
    document.querySelector('#root') 
); 

Update

Динамическая высота теперь работает со следующим кодом с CellMeasurer. Но, к сожалению, this.loadMoreRows() функция не вызывается в InfiniteLoader. Без CellMeasurer также он не работает. Я не уверен, что я сделал неправильно в следующем коде.

import React, { Component } from 'react'; 
import { AutoSizer, CellMeasurer, InfiniteLoader, List } from 'react-virtualized'; 
import _ from 'lodash'; 

class InfiniteList extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     list: props.list, 
     loading: false 
    }; 
    } 
    componentDidMount() { 
    fetch('http://jsonplaceholder.typicode.com/comments') 
     .then((response) => { 
     response.json().then((data) => { 
      this.setState({ 
      list: _.concat(this.state.list, _.map(data, 'body')), 
      loading: false 
      }); 
     }); 
     }); 
    } 
    isRowLoaded({ index }) { 
    return !!this.state.list[index]; 
    } 

    loadMoreRows({ startIndex, stopIndex }) { 
    if (this.state.loading) { 
     return; 
    } 
    this.setState({ 
     loading: true 
    }); 
    return fetch('http://jsonplaceholder.typicode.com/comments') 
     .then((response) => { 
     response.json().then((data) => { 
      // Simulate delay 
      setTimeout(() => { 
      this.setState({ 
       list: _.concat(this.state.list, _.map(data, 'body')), 
       loading: false 
      }); 
      }, 3000); 
     }); 
     }); 
    } 

    rowRenderer({ key, index, isScrolling, isVisible, style }) { 
    if (isVisible) { 
     return (
     <div key={key} style={style}>#{index} {this.state.list[index]}.</div> 
    ); 
    } 
    } 
    cellRenderer({ columnIndex, key, rowIndex, style }) { 
    return (
     <div 
     key={key} 
     style={style} 
     > 
     <div>#{rowIndex} {this.state.list[rowIndex]}.</div> 
     </div> 
    ); 
    } 
    render() { 
    return (
     <div> 
     <InfiniteLoader 
      isRowLoaded={isRowLoaded => this.isRowLoaded(isRowLoaded)} 
      loadMoreRows={loadMoreRows => this.loadMoreRows(loadMoreRows)} 
      rowCount={this.state.list.length} 
     > 
      {({ onRowsRendered, registerChild }) => (
      <AutoSizer disableHeight> 
       {({ width }) => (
       <CellMeasurer 
        cellRenderer={cellRenderer => this.cellRenderer(cellRenderer)} 
        columnCount={1} 
        rowCount={this.state.list.length} 
       > 
        {({ getRowHeight }) => (
        <List 
         onRowsRendered={onRowsRendered} 
         ref={registerChild} 
         width={width} 
         height={400} 
         rowCount={this.state.list.length} 
         rowHeight={getRowHeight} 
         rowRenderer={rowRenderer => this.rowRenderer(rowRenderer)} 
        /> 
       )} 
       </CellMeasurer> 
      )} 
      </AutoSizer> 
     )} 
     </InfiniteLoader> 
     {this.state.loading && <p>Loading...</p>} 
     </div> 
    ); 
    } 
} 

const list = []; 

ReactDOM.render(
    <InfiniteList list={list} />, 
    document.querySelector('#root') 
); 

Любая помощь будет оценена по достоинству. Благодаря!

ответ

0

Вы должны написать computeRowHeight самостоятельно, чтобы определить высоту строки. В некоторых случаях, основываясь на индексе и свойствах этой строки, вы можете узнать, какой будет высота строки. Например, если ваши строки могут быть разными компонентами, если вы знаете, что определенная строка будет компонентом A с высотой 40, а другая строка будет компонентом B с высотой 60, вы можете проверить эти реквизиты и вернуть правильную высоту.

Если вы не знаете высот, вам придется фактически посмотреть на элемент в DOM и выяснить его высоту. Если он еще не существует в DOM, вам нужно сначала вернуть наилучшее предположение, а затем вызвать recomputeRowHeights после рендера и затем осмотреть DOM.

+1

Если вы ответите на ответ Дрю, возможно, вы захотите использовать другой виртуализованный компонент, такой как CellMeasurer, если вы ничего не знаете о размере вашего контента. Я также слышал о людях, использующих реактивную меру с реакцией-виртуализацией с хорошими результатами. – brianvaughn

+0

@brianvaughn Спасибо! Раньше я не мог получить динамическую высоту с помощью CellMeasurer. Но я снова попробовал, и теперь он работает (хотя иногда несколько строк перекрываются). Но, к сожалению, моя функция this.loadMoreRows() 'не получает вызов в InfiniteLoader. Я думаю, что он также не работал перед CellMeasurer. Так что это не имеет ничего общего с CellMeasurer. Я не уверен, что я делаю неправильно здесь. Спасибо за ваше время! – krishnaxv

+0

Я понял это. Я должен дать произвольное большое число в 'rowCount' в' InfiniteLoader' вместо 'rowCount = {this.state.list.length}'. – krishnaxv

 Смежные вопросы

  • Нет связанных вопросов^_^