如何使用动态列表高度进行反应虚拟化

时间:2017-03-27 18:09:58

标签: reactjs react-virtualized

我正在尝试将反应虚拟化实施到我的项目中。我有一个带有细分列表的侧面板。当用户选择项目时,我希望有类似手风琴的功能。页面首次加载时,看起来它正常工作。

screenshot

然而,当我开始向下滚动时,列表看起来像这样

screenshot2

这是代码

const mapStateToProps = state => ({
  windowHeight: state.dimensions.windowHeight,
  sbds: new Immutable.List(state.sbds.data),
  sbd: state.sbd.data
})

@connect(mapStateToProps)
export default class SBD extends Component {
  static propTypes = {
    windowHeight: PropTypes.number,
    sbds: PropTypes.instanceOf(Immutable.List),
    sbd: PropTypes.object
  }

  constructor(props) {
    super(props)
    this.state = {
      listHeight: props.windowHeight - 250,
      listRowHeight: 60,
      overscanRowCount: 10,
      rowCount: props.sbds.size,
      scrollToIndex: undefined,
      collapse: true
    }
  }

  componentWillUnmount() {
  }

  shouldComponentUpdate(nextProps, nextState) {
    const {sbds} = this.props
    if (shallowCompare(this, nextProps, nextState))
      return true
    else return stringify(sbds) !== stringify(nextProps.sbds)
  }

  _handleSelectRow = selected => {
    sbdRequest(selected)
    const obj = {[selected.id]: true}
    this.setState(obj)
  }

  render() {
    const {
      listHeight,
      listRowHeight,
      overscanRowCount,
      rowCount,
      scrollToIndex
    } = this.state

    return (
      <div>
        <SearchGroup />
        <Card className='border-0 mt-10 mb-0'>
          <CardBlock className='p-0'>
            <AutoSizer disableHeight>
              {({width}) => (
                <List
                  ref='List'
                  className=''
                  height={listHeight}
                  overscanRowCount={overscanRowCount}
                  rowCount={rowCount}
                  rowHeight={listRowHeight}
                  rowRenderer={this._rowRenderer}
                  scrollToIndex={scrollToIndex}
                  width={width}
                />
              )}
            </AutoSizer>
          </CardBlock>
        </Card>
      </div>
    )
  }

  _getDatum = index => {
    const {sbds} = this.props
    return sbds.get(index % sbds.size)
  }

  _rowRenderer = ({index}) => {
    const {sbd} = this.props
    const datum = this._getDatum(index)
    return (
      <span key={datum.id}>
        <Button
          type='button'
          color='link'
          block
          onClick={() => this._handleSelectRow(datum)}>
          {datum.name}
        </Button>
        <Collapse isOpen={this.state[datum.id]}>
          <Card>
            <CardBlock>
            FOO BAR
            </CardBlock>
          </Card>
        </Collapse>
      </span>
    )
  }
}

1 个答案:

答案 0 :(得分:1)

您没有设置style参数(传递给您的rowRenderer)。这是绝对定位行的东西。没有它,它们会在你滚动时叠加在顶部/左侧。

https://bvaughn.github.io/forward-js-2017/#/32/1