I have gone through many answers on StackOverflow. I have also gone through List document here, react-virtualized/List. But, still I am not able to understand how to dynamically set row height in react-virtualized List. How to calculate the height in rowHeight
prop function?
I can call my function like rowHeight={({ index }) => this.computeRowHeight({ index })}
. But how will the function compute the row height?
Following 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 is now working with the following code with CellMeasurer
. But, unfortunately this.loadMoreRows()
function is not called in InfiniteLoader
. Without CellMeasurer
also it is not working. 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 will be appreciated. Thanks!