2017-02-13 4 views
0

genannt Ich habe folgendes Beispiel die InfiniteLoader mit einem Table Implementierung, die die TablerowCount auf eine bekannte große Anzahl (Anzahl der Protokolle in der db) setzt und die InfiniteLoaderrowCount auf die Größe des Charge Logs, die ich hole. Ich brauche das, damit der Benutzer weiß, wie viele Daten auf der Scroll-Höhe basieren. Andernfalls müsste er bis zum Ende scrollen und sehen, ob mehr Protokolle geladen sind. Könnte sein, dass ich die zwei rowCount Requisiten missbrauche, aber wenn ich schnell zu einem Index nahe dem Ende scrollen, wo Daten noch nicht geladen sind, ist data undefined in der getRowClassName Funktion. Ich nahm an, die loadMoreRows würde in diesem Fall aufgerufen werden.undefiniert Index nach loadMoreRows wird

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) 
       }); 
      }); 
    } 
}; 

Antwort

0

Könnte sein, dass ich die beiden rowCount Requisiten bin mißbrauchen

Sie sollten beide den gleichen rowCount Wert InfiniteLoader passieren und Table. Es sollte entweder die Gesamtgröße aller Ihrer Daten auf dem Server sein (wie gezeigt here) oder die Größe Ihrer lokalen Daten +1, um das Laden mehr zu erlauben, wenn ein Benutzer nahe dem Ende scrollt (wie gezeigt here).

Immer wenn ich schnell zu einem Index nahe dem Ende scrolle, wo Daten noch nicht geladen sind, sind Daten in der getRowClassName-Funktion nicht definiert. Ich nahm an, die loadMoreRows würde in diesem Fall aufgerufen werden.

loadMoreRows wird aufgerufen - aber es ist asynchron. Reaktiv-virtualisiert blockiert den Benutzer nicht, bis Daten geladen werden. Ihre getRowClassName-Funktion muss mit der Tatsache umgehen, dass ein Benutzer möglicherweise schneller scrollt, als Ihre Lazy-Loaded-Daten laden können. Wenn Sie möchten, können Sie eine andere "Ladevorgang läuft" - Benutzeroberfläche für nicht entladene Zeilen anzeigen.

+0

Also, die Art, wie ich die 2 'rowCount's verwende, ist korrekt? – XeniaSis

+0

Entschuldigung, ich habe diesen Teil Ihrer Frage verpasst. Bearbeitete meine Antwort, um etwas mehr Details zu enthalten. – brianvaughn

+0

Auf der ersten Verknüpfung, die Sie mit der Gesamtzahl angegeben haben, wird nicht dieselbe Anzahl verwendet. Der 'InfiniteLoader' verwendet ein undefiniertes' remoteRowCount', während die 'Tabelle' das' list.length' verwendet. – XeniaSis

Verwandte Themen