加载时未调用 loadMoreRows
loadMoreRows not called on load
我有以下示例实现 InfiniteLoader
和 Table
。问题是 loadMoreRows
不会在加载时或安装组件时调用。但是,如果我手动执行 API 调用并通过 props
传递结果,loadMoreRows
将使用 startIndex 0 调用,因此我有相同的 API 调用两次。
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'
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 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),
loadedRowsMap
});
});
}
};
The problem is that loadMoreRows
is not called on load or when the component is mounted.
Any time a range of rows loads, InfiniteLoader
calls isRowLoaded
for each row to determine if it needs to be loaded. If isRowLoaded
returns false, then that row is queued up and loadMoreRows
is called in chunks for each range of unloaded rows.
在你上面的例子中,我 相信 发生的事情是你没有将任何初始行传递给 Table
- 所以 Grid
不是最初渲染任何东西(因为它没有要渲染的行),所以我上面链接的 rows-loaded 调用者没有什么要迭代的,也没有什么要加载的。你在这里有几个选择——要么自己开始第一次加载,要么添加一个 +1 空行来提示 InfiniteLoader
它应该请求更多数据 (like I do in this example)。
我有以下示例实现 InfiniteLoader
和 Table
。问题是 loadMoreRows
不会在加载时或安装组件时调用。但是,如果我手动执行 API 调用并通过 props
传递结果,loadMoreRows
将使用 startIndex 0 调用,因此我有相同的 API 调用两次。
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'
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 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),
loadedRowsMap
});
});
}
};
The problem is that
loadMoreRows
is not called on load or when the component is mounted.
Any time a range of rows loads, InfiniteLoader
calls isRowLoaded
for each row to determine if it needs to be loaded. If isRowLoaded
returns false, then that row is queued up and loadMoreRows
is called in chunks for each range of unloaded rows.
在你上面的例子中,我 相信 发生的事情是你没有将任何初始行传递给 Table
- 所以 Grid
不是最初渲染任何东西(因为它没有要渲染的行),所以我上面链接的 rows-loaded 调用者没有什么要迭代的,也没有什么要加载的。你在这里有几个选择——要么自己开始第一次加载,要么添加一个 +1 空行来提示 InfiniteLoader
它应该请求更多数据 (like I do in this example)。