调用 loadMoreRows 后的未定义索引
Undefined index after loadMoreRows is called
我有以下示例使用 Table
实现 InfiniteLoader
,它将 Table
rowCount
设置为一个已知的大数字(数据库中的日志计数) 和 InfiniteLoader
rowCount
到我获取的那批日志的大小。我需要这个,以便用户根据滚动高度知道有多少数据。否则,他将不得不滚动到末尾并查看是否加载了更多日志。可能是我误用了两个 rowCount
道具,但每当我快速滚动到接近末尾的索引时,数据尚未加载,data
在 getRowClassName
中未定义功能。我假设 loadMoreRows
在这种情况下会被调用。
import React = require('react');
import _ = require('lodash');
import Immutable = require('immutable');
import Api = require('./Api');
const STATUS_LOADING = 1,
STATUS_LOADED = 2,
LOG_LIMIT = 200;
interface Props {
logEntries: Immutable.List<Immutable.Map<string, any>>;
}
interface State {
logEntries?: Immutable.List<Immutable.Map<string, any>>;
count?: number;
loadedRowsMap?: any;
}
class LogViewer extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
logEntries: props.logEntries,
count: 0,
loadedRowsMap: {}
};
}
render() {
return {this.renderLoader()};
}
private renderLoader() {
const {logEntries, count} = this.state;
return (
<InfiniteLoader isRowLoaded={this.isRowLoaded.bind(this)}
loadMoreRows={this.loadMoreRows.bind(this)}
minimumBatchSize={LOG_LIMIT}
rowCount={logEntries.size} >
{
({onRowsRendered, registerChild}) => (
<AutoSizer disableHeight>
{
({width}) => (
<Table headerHeight={20}
height={400}
onRowsRendered={onRowsRendered}
ref={registerChild}
rowCount={count}
className='log-entries'
gridClassName='grid'
rowClassName={this.getRowClassName.bind(this)}
headerStyle={{ fontSize: 15 }}
rowGetter={({index}) => logEntries.get(index)}
rowHeight={50}
width={width} >
<Column label='Name'
key='name'
dataKey='name'
width={200} />
</Table>
)
}
</AutoSizer>
)
}
</InfiniteLoader>
);
}
private getRowClassName({index}) {
const {logEntries} = this.state;
if(index > -1) {
const data = logEntries.get(index);
return `log-entry ${data.get('name').toLowerCase()}`;
}
return '';
}
private isRowLoaded({index}) {
const {loadedRowsMap} = this.state;
return !!loadedRowsMap[index];
}
private loadMoreRows({startIndex, stopIndex}) {
const {loadedRowsMap, level, logEntries} = this.state;
_.range(startIndex, stopIndex).forEach(i => {
loadedRowsMap[i] = STATUS_LOADING;
});
this.setState({ loadedRowsMap });
const offset = Math.floor((startIndex + 1) / LOG_LIMIT);
return Api.logs(LOG_LIMIT, offset)
.then(({body: [count, logs]}) => {
_.range(startIndex, stopIndex).forEach(i => {
loadedRowsMap[i] = STATUS_LOADED;
});
const newLogs = logEntries.toJS().concat(logs);
this.setState({
count,
logEntries: Immutable.fromJS(newLogs)
});
});
}
};
Could be that I'm misusing the two rowCount
props
您应该将相同的 rowCount
值传递给 InfiniteLoader
和 Table
。它应该是服务器上所有数据的总大小(如图所示here) or the size of your local data +1 to allow loading more when a user scrolls near the end (as shown here)。
whenever I scroll fast to an index close to the end, where data is not loaded yet, data is undefined in the getRowClassName
function. I assumed the loadMoreRows
would get called in this case.
loadMoreRows
确实被调用了——但它是异步的。 react-virtualized 在数据加载之前不会阻止用户滚动。您的 getRowClassName
函数需要处理这样一个事实,即用户滚动的速度可能比您的 lazy-loaded 数据能够加载的速度快。如果您愿意,可以为卸载的行显示不同的 "load in progress" UI。
我有以下示例使用 Table
实现 InfiniteLoader
,它将 Table
rowCount
设置为一个已知的大数字(数据库中的日志计数) 和 InfiniteLoader
rowCount
到我获取的那批日志的大小。我需要这个,以便用户根据滚动高度知道有多少数据。否则,他将不得不滚动到末尾并查看是否加载了更多日志。可能是我误用了两个 rowCount
道具,但每当我快速滚动到接近末尾的索引时,数据尚未加载,data
在 getRowClassName
中未定义功能。我假设 loadMoreRows
在这种情况下会被调用。
import React = require('react');
import _ = require('lodash');
import Immutable = require('immutable');
import Api = require('./Api');
const STATUS_LOADING = 1,
STATUS_LOADED = 2,
LOG_LIMIT = 200;
interface Props {
logEntries: Immutable.List<Immutable.Map<string, any>>;
}
interface State {
logEntries?: Immutable.List<Immutable.Map<string, any>>;
count?: number;
loadedRowsMap?: any;
}
class LogViewer extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
logEntries: props.logEntries,
count: 0,
loadedRowsMap: {}
};
}
render() {
return {this.renderLoader()};
}
private renderLoader() {
const {logEntries, count} = this.state;
return (
<InfiniteLoader isRowLoaded={this.isRowLoaded.bind(this)}
loadMoreRows={this.loadMoreRows.bind(this)}
minimumBatchSize={LOG_LIMIT}
rowCount={logEntries.size} >
{
({onRowsRendered, registerChild}) => (
<AutoSizer disableHeight>
{
({width}) => (
<Table headerHeight={20}
height={400}
onRowsRendered={onRowsRendered}
ref={registerChild}
rowCount={count}
className='log-entries'
gridClassName='grid'
rowClassName={this.getRowClassName.bind(this)}
headerStyle={{ fontSize: 15 }}
rowGetter={({index}) => logEntries.get(index)}
rowHeight={50}
width={width} >
<Column label='Name'
key='name'
dataKey='name'
width={200} />
</Table>
)
}
</AutoSizer>
)
}
</InfiniteLoader>
);
}
private getRowClassName({index}) {
const {logEntries} = this.state;
if(index > -1) {
const data = logEntries.get(index);
return `log-entry ${data.get('name').toLowerCase()}`;
}
return '';
}
private isRowLoaded({index}) {
const {loadedRowsMap} = this.state;
return !!loadedRowsMap[index];
}
private loadMoreRows({startIndex, stopIndex}) {
const {loadedRowsMap, level, logEntries} = this.state;
_.range(startIndex, stopIndex).forEach(i => {
loadedRowsMap[i] = STATUS_LOADING;
});
this.setState({ loadedRowsMap });
const offset = Math.floor((startIndex + 1) / LOG_LIMIT);
return Api.logs(LOG_LIMIT, offset)
.then(({body: [count, logs]}) => {
_.range(startIndex, stopIndex).forEach(i => {
loadedRowsMap[i] = STATUS_LOADED;
});
const newLogs = logEntries.toJS().concat(logs);
this.setState({
count,
logEntries: Immutable.fromJS(newLogs)
});
});
}
};
Could be that I'm misusing the two
rowCount
props
您应该将相同的 rowCount
值传递给 InfiniteLoader
和 Table
。它应该是服务器上所有数据的总大小(如图所示here) or the size of your local data +1 to allow loading more when a user scrolls near the end (as shown here)。
whenever I scroll fast to an index close to the end, where data is not loaded yet, data is undefined in the
getRowClassName
function. I assumed theloadMoreRows
would get called in this case.
loadMoreRows
确实被调用了——但它是异步的。 react-virtualized 在数据加载之前不会阻止用户滚动。您的 getRowClassName
函数需要处理这样一个事实,即用户滚动的速度可能比您的 lazy-loaded 数据能够加载的速度快。如果您愿意,可以为卸载的行显示不同的 "load in progress" UI。