How to adjust dynamic row height in an interactive virtualized list?

I went through many answers to Kara. I also looked at the list of documents here, reacts to virtualization / list . But I still can’t figure out how to dynamically set the line height in a responsive-virtualized list. How to calculate the height in the support rowHeight?

I can name my function as rowHeight={({ index }) => this.computeRowHeight({ index })}. But how will the function calculate the height of the line?

Below is the code for reference.

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

Dynamic height now works with the following code from CellMeasurer. But, unfortunately, the function is this.loadMoreRows()not called in InfiniteLoader. Without CellMeasureralso does not work. I am not sure what I did wrong in the following code.

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')
);

Any help would be appreciated. Thank!

+7
2

computeRowHeight , . , , , . , , , A 40, B 60, .

, DOM . DOM, , recomputeRowHeights DOM.

0

, , , , , . Table react hooks, . , .

0

Source: https://habr.com/ru/post/1665368/


All Articles