抱歉,如果标题有些误导。我正在使用InfiniteLoader
a Table
,问题是我要加载的数据总数几乎总是巨大的。如果每次loadMoreRows
调用时都附加数据,我最终会在状态中存储超过 100000 个条目,我认为这对性能不利。
我想知道是否可以不每次都附加数据。我尝试仅将日志和状态设置为仅从 to 加载startIndex
,stopIndex
但每次滚动loadMoreRows
都会被多次调用。
这是我到目前为止所拥有的,如上所述我尝试过的
'use strict';
import React = require('react');
import _ = require('lodash');
import Immutable = require('immutable');
import moment = require('moment-timezone');
import {AutoSizer, InfiniteLoader, Table, Column} from 'react-virtualized';
interface Props {
logEntries: Immutable.List<Immutable.Map<string, any>>;
count: number;
timezone: string;
logLimit: number;
loadedRowsMap: { [index: number]: number; };
onLoadMoreRows: (param: {startIndex: number, stopIndex: number}) => Promise<any>;
}
class LogLoader extends React.Component<Props, {}> {
render() {
const {logEntries, count, logLimit} = this.props;
const headers: {
name: string;
dataKey: string;
width: number;
cellDataGetter?: (param: {rowData: any}) => any;
}[] = [
{ name: 'Time', dataKey: 'dtCreated', width: 95, cellDataGetter: this.renderTime.bind(this) },
{ name: 'Level', dataKey: 'levelname', width: 65 },
{ name: 'Message', dataKey: 'message', width: 70, cellDataGetter: this.renderMessage.bind(this) }
];
return (
<InfiniteLoader isRowLoaded={this.isRowLoaded.bind(this)}
loadMoreRows={this.props.onLoadMoreRows}
minimumBatchSize={logLimit}
rowCount={count} >
{
({onRowsRendered, registerChild}) => (
<AutoSizer disableHeight>
{
({width}) => (
<Table headerHeight={20}
height={400}
onRowsRendered={onRowsRendered}
rowRenderer={this.rowRenderer}
ref={registerChild}
rowCount={count}
className='log-entries'
gridClassName='grid'
headerClassName='header'
rowClassName={this.getRowClassName.bind(this)}
rowGetter={({index}) => logEntries.get(index)}
rowHeight={this.calculateRowHeight.bind(this)}
width={width} >
{
headers.map(({name, dataKey, cellDataGetter, width}) =>
<Column label={name}
key={name}
className={`${name.toLowerCase()} column`}
dataKey={dataKey}
cellDataGetter={cellDataGetter || this.renderTableCell.bind(this)}
width={width} />
)
}
</Table>
)
}
</AutoSizer>
)
}
</InfiniteLoader>
);
}
private calculateRowHeight({index}) {
const rowData = this.props.logEntries.get(index);
if(!rowData) {
return 0;
}
const msg = this.renderMessage({rowData});
const div = document.createElement('div');
const span = document.createElement('span');
span.style.whiteSpace = 'pre';
span.style.wordBreak = 'break-all';
span.style.fontSize = '12px';
span.style.fontFamily = 'monospace';
span.style.display = 'table-cell';
span.innerHTML = msg;
div.appendChild(span);
document.body.appendChild(div);
const height = div.offsetHeight;
document.body.removeChild(div);
return height;
}
private rowRenderer(params: any) {
const {key, className, columns, rowData, style} = params;
if(!rowData) {
return (
<div className={className}
key={key}
style={style} >
Loading...
</div>
);
}
return (
<div className={className}
key={key}
style={style} >
{columns}
</div>
);
}
private renderTableCell({rowData, dataKey}) {
if(!rowData) {
return null;
}
return rowData.get(dataKey);
}
private renderMessage({rowData}) {
if(!rowData) {
return null;
}
return rowData.get('message');
}
private renderTime({rowData}) {
if(!rowData) {
return null;
}
return moment(rowData.get('dtCreated'))
.tz(this.props.timezone)
.format('HH:mm:ss.SSS');
}
private getRowClassName({index}) {
const {logEntries} = this.props;
const data = logEntries.get(index);
if(data) {
return `log-entry ${data.get('levelname').toLowerCase()}`;
}
return '';
}
private isRowLoaded({index}) {
return !!this.props.loadedRowsMap[index];
}
}
export = LogLoader;
这里是loadMoreRows
从父组件传下来的
private loadMoreRows({startIndex, stopIndex}) {
const {loadedRowsMap, logEntries} = this.state,
indexRange = _.range(startIndex, stopIndex + 1),
updatedLoadedRowsMap = {};
indexRange.forEach(i => { updatedLoadedRowsMap[i] = STATUS_LOADING; });
this.setState({ loadedRowsMap: updatedLoadedRowsMap, loading: true });
return Api.scriptLogs(null, { id: this.props.id })
.then(({body: [count, logs]}) => {
indexRange.forEach(i => { updatedLoadedRowsMap[i] = STATUS_LOADED; });
const newLogs = logEntries.splice((stopIndex - startIndex + 1), 0, ...logs).toJS();
this.setState({
count,
logEntries: Immutable.fromJS(newLogs),
loadedRowsMap: updatedLoadedRowsMap,
loading: false
});
});
}