reactjs - 如何在react-virtualized List中设置动态行高?

标签 reactjs react-virtualized

我在 StackOverflow 上查看了很多答案。我还浏览了此处的列表文档,react-virtualized/List 。但是,我仍然无法理解如何在 react-virtualized 列表中动态设置行高。如何在rowHeight prop函数中计算高度?

我可以像 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')
);

任何帮助将不胜感激。谢谢!

最佳答案

您需要自己编写computeRowHeight来确定行的高度。在某些情况下,根据该行的索引和属性,您可能能够知道该行的高度。例如,如果您的行可能是不同的组件,如果您知道某一行将是高度为 40 的组件 A,另一行将是高度为 60 的组件 B,您可以检查这些 props 并返回正确的高度。

如果您不知道高度,那么您将必须实际查看 DOM 中的元素并计算出它的高度。如果 DOM 中尚不存在,您需要首先返回最佳猜测,然后调用 recomputeRowHeights然后渲染并检查 DOM。

关于reactjs - 如何在react-virtualized List中设置动态行高?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41402677/

相关文章:

javascript - Next.js 中具有嵌套组件路由渲染功能的等效路由?

android - React Native 中的存储

javascript - react : Is a component entirely re-rendered on every setState()?

react-virtualized - InfiniteLoader 在loadMoreRows 完成后向上滚动时跳转

reactjs - 如何在虚拟化列表中使用选择下拉列表?

node.js - React 没有获取环境变量

javascript - react Redux 表单 : form is submiting with old values

reactjs - 如何使用 react 虚拟化列表对可扩展行进行行高调整进行故障排除?

react-virtualized - 重置行高会导致计算不正确的行偏移

javascript - 如何使用 React js 创建图像虚拟滚动