Große Listenleistung mit React

86

Ich bin dabei, eine filterbare Liste mit React zu implementieren. Die Struktur der Liste ist wie in der Abbildung unten dargestellt.

Geben Sie hier die Bildbeschreibung ein

PRÄMISSE

Hier ist eine Beschreibung, wie es funktionieren soll:

  • Der Status befindet sich in der Komponente der höchsten Ebene, der SearchKomponente.
  • Der Zustand wird wie folgt beschrieben:
{
    sichtbar: boolean,
    Dateien: Array,
    gefiltert: Array,
    Abfrage: Zeichenfolge,
    currentSelectedIndex: Ganzzahl
}}
  • files ist ein potenziell sehr großes Array mit Dateipfaden (10000 Einträge sind eine plausible Zahl).
  • filteredist das gefilterte Array, nachdem der Benutzer mindestens 2 Zeichen eingegeben hat. Ich weiß, dass es sich um abgeleitete Daten handelt, und als solches könnte man argumentieren, sie im Staat zu speichern, aber es wird für benötigt
  • currentlySelectedIndex Dies ist der Index des aktuell ausgewählten Elements aus der gefilterten Liste.

  • Der Benutzer gibt mehr als 2 Buchstaben in die InputKomponente ein, das Array wird gefiltert und für jeden Eintrag im gefilterten Array wird eine ResultKomponente gerendert

  • Jede ResultKomponente zeigt den vollständigen Pfad an, der teilweise mit der Abfrage übereinstimmt, und der teilweise übereinstimmende Teil des Pfads wird hervorgehoben. Zum Beispiel wäre das DOM einer Ergebniskomponente, wenn der Benutzer 'le' eingegeben hätte, ungefähr so:

    <li>this/is/a/fi<strong>le</strong>/path</li>

  • Wenn der Benutzer die Aufwärts- oder Abwärtstaste drückt, während die InputKomponente fokussiert ist, werden die currentlySelectedIndexÄnderungen basierend auf dem filteredArray vorgenommen. Dadurch wird die ResultKomponente, die dem Index entspricht, als ausgewählt markiert, was zu einem erneuten Rendern führt

PROBLEM

Anfangs habe ich dies mit einem ausreichend kleinen Array filesunter Verwendung der Entwicklungsversion von React getestet , und alles hat gut funktioniert.

Das Problem trat auf, als ich mich mit einem filesArray mit bis zu 10000 Einträgen befassen musste . Wenn Sie 2 Buchstaben in die Eingabe eingeben, wird eine große Liste erstellt, und wenn ich die Auf- und Ab-Tasten zum Navigieren drücke, ist dies sehr verzögert.

Zuerst hatte ich keine definierte Komponente für die ResultElemente und ich erstellte lediglich die Liste im laufenden Betrieb bei jedem Rendering der SearchKomponente als solche:

results  = this.state.filtered.map(function(file, index) {
    var start, end, matchIndex, match = this.state.query;

     matchIndex = file.indexOf(match);
     start = file.slice(0, matchIndex);
     end = file.slice(matchIndex + match.length);

     return (
         <li onClick={this.handleListClick}
             data-path={file}
             className={(index === this.state.currentlySelected) ? "valid selected" : "valid"}
             key={file} >
             {start}
             <span className="marked">{match}</span>
             {end}
         </li>
     );
}.bind(this));

Wie Sie sehen können, würde jedes Mal, wenn die currentlySelectedIndexÄnderung vorgenommen wird, ein erneutes Rendern verursacht und die Liste jedes Mal neu erstellt. Ich dachte, da ich keyfür jedes liElement einen Wert festgelegt hatte, würde React vermeiden, jedes andere liElement neu zu rendern , das seine classNameÄnderung nicht hatte, aber anscheinend war es nicht so.

Am Ende habe ich eine Klasse für die ResultElemente definiert, in der explizit geprüft wird, ob jedes ResultElement neu gerendert werden soll, basierend darauf, ob es zuvor ausgewählt wurde und basierend auf der aktuellen Benutzereingabe:

var ResultItem = React.createClass({
    shouldComponentUpdate : function(nextProps) {
        if (nextProps.match !== this.props.match) {
            return true;
        } else {
            return (nextProps.selected !== this.props.selected);
        }
    },
    render : function() {
        return (
            <li onClick={this.props.handleListClick}
                data-path={this.props.file}
                className={
                    (this.props.selected) ? "valid selected" : "valid"
                }
                key={this.props.file} >
                {this.props.children}
            </li>
        );
    }
});

Und die Liste wird jetzt als solche erstellt:

results = this.state.filtered.map(function(file, index) {
    var start, end, matchIndex, match = this.state.query, selected;

    matchIndex = file.indexOf(match);
    start = file.slice(0, matchIndex);
    end = file.slice(matchIndex + match.length);
    selected = (index === this.state.currentlySelected) ? true : false

    return (
        <ResultItem handleClick={this.handleListClick}
            data-path={file}
            selected={selected}
            key={file}
            match={match} >
            {start}
            <span className="marked">{match}</span>
            {end}
        </ResultItem>
    );
}.bind(this));
}

Dies hat die Leistung etwas verbessert , ist aber immer noch nicht gut genug. Als ich die Produktionsversion von React testete, funktionierten die Dinge butterweich und ohne Verzögerung.

ENDEFFEKT

Ist eine solche merkliche Diskrepanz zwischen Entwicklungs- und Produktionsversionen von React normal?

Verstehe / mache ich etwas falsch, wenn ich darüber nachdenke, wie React die Liste verwaltet?

UPDATE 14-11-2016

Ich habe diese Präsentation von Michael Jackson gefunden, in der er ein Problem behandelt, das diesem sehr ähnlich ist: https://youtu.be/7S8v8jfLb1Q?t=26m2s

Die Lösung ist der in der Antwort von AskarovBeknar unten vorgeschlagenen sehr ähnlich

UPDATE 14-4-2018

Da dies anscheinend eine beliebte Frage ist und sich die Dinge seit der ursprünglichen Frage weiterentwickelt haben, empfehle ich Ihnen, das oben verlinkte Video anzusehen, um sich ein Bild von einem virtuellen Layout zu machen. Ich empfehle Ihnen jedoch auch, React Virtualized zu verwenden Bibliothek, wenn Sie das Rad nicht neu erfinden möchten.

Dimitris Karagiannis
quelle
Was meinst du mit Entwicklungs- / Produktionsversion von reagieren?
Dibesjr
@Dibesjr facebook.github.io/react/…
Dimitris Karagiannis
Ah, ich verstehe, danke. Um eine Ihrer Fragen zu beantworten, gibt es eine Diskrepanz bei der Optimierung zwischen den Versionen. Eine Sache, auf die Sie in großen Listen achten sollten, ist das Erstellen von Funktionen in Ihrem Rendering. Es wird einen Leistungseinbruch haben, wenn Sie in riesige Listen geraten. Ich würde versuchen zu sehen, wie lange es dauert, diese Liste mit ihren Perf-Tools zu
erstellen
2
Ich denke, Sie sollten die Verwendung von Redux überdenken, da es genau das ist, was Sie hier benötigen (oder jede Art von Flussmittelimplementierung). Sie sollten sich auf
jeden Fall
2
Ich bezweifle, dass ein Benutzer einen Vorteil darin hat, durch 10000 Ergebnisse zu scrollen. Was ist, wenn Sie nur die Top-100-Ergebnisse oder so rendern und diese basierend auf der Abfrage aktualisieren?
Koen.

Antworten:

18

Wie bei vielen anderen Antworten auf diese Frage liegt das Hauptproblem in der Tatsache, dass das Rendern so vieler Elemente im DOM beim Filtern und Behandeln von Schlüsselereignissen langsam sein wird.

Sie machen in Bezug auf React, das das Problem verursacht, nichts von Natur aus falsch, aber wie viele der leistungsbezogenen Probleme kann auch die Benutzeroberfläche einen großen Prozentsatz der Schuld tragen.

Wenn Ihre Benutzeroberfläche nicht auf Effizienz ausgelegt ist, leiden auch Tools wie React, die auf Leistung ausgelegt sind.

Das Filtern der Ergebnismenge ist ein guter Anfang, wie von @Koen erwähnt

Ich habe ein bisschen mit der Idee herumgespielt und eine Beispiel-App erstellt, die zeigt, wie ich anfangen kann, diese Art von Problem anzugehen.

Dies ist keineswegs production readyCode, aber er veranschaulicht das Konzept angemessen und kann modifiziert werden, um robuster zu sein. Schauen Sie sich den Code an - ich hoffe, es gibt Ihnen zumindest einige Ideen ...;)

React-Large-List-Beispiel

Geben Sie hier die Bildbeschreibung ein

deowk
quelle
1
Ich fühle mich wirklich schlecht, wenn ich nur eine Antwort auswählen muss, sie scheinen alle Mühe zu haben, aber ich bin derzeit im Urlaub ohne PC und kann sie nicht wirklich mit der Aufmerksamkeit überprüfen, die sie verdienen. Ich habe mich für dieses entschieden, weil es kurz genug und auf den Punkt gebracht ist, um es auch beim Lesen von einem Telefon aus zu verstehen. Lahmer Grund, den ich kenne.
Dimitris Karagiannis
Was meinst du mit Hostdatei bearbeiten 127.0.0.1 * http://localhost:3001?
Stackjlei
@stackjlei Ich denke, er meinte die Zuordnung von 127.0.0.1 zu localhost: 3001 in / etc / hosts
Maverick
16

Meine Erfahrung mit einem sehr ähnlichen Problem ist, dass die Reaktion wirklich leidet, wenn mehr als 100-200 Komponenten gleichzeitig im DOM vorhanden sind. Selbst wenn Sie sehr vorsichtig sind (indem Sie alle Schlüssel einrichten und / oder eine shouldComponentUpdateMethode implementieren ), um nur eine oder zwei Komponenten bei einem erneuten Rendern zu ändern, befinden Sie sich immer noch in einer Welt voller Verletzungen.

Der langsame Teil der Reaktion im Moment ist, wenn der Unterschied zwischen dem virtuellen DOM und dem realen DOM verglichen wird. Wenn Sie Tausende von Komponenten haben, aber nur ein paar aktualisieren, spielt es keine Rolle, dass React immer noch einen massiven Unterschied zwischen den DOMs hat.

Wenn ich jetzt Seiten schreibe, versuche ich, sie so zu gestalten, dass die Anzahl der Komponenten minimiert wird. Eine Möglichkeit, dies beim Rendern großer Listen von Komponenten zu tun, besteht darin, ... nun ... keine großen Listen von Komponenten zu rendern.

Was ich damit meine ist: Rendern Sie nur die Komponenten, die Sie derzeit sehen können, rendern Sie mehr, während Sie nach unten scrollen. Ihr Benutzer wird wahrscheinlich nicht durch Tausende von Komponenten nach unten scrollen. Ich hoffe.

Eine großartige Bibliothek dafür ist:

https://www.npmjs.com/package/react-infinite-scroll

Mit einer tollen Anleitung hier:

http://www.reactexamples.com/react-infinite-scroll/

Ich befürchte, es werden keine Komponenten entfernt, die sich oben auf der Seite befinden. Wenn Sie also lange genug scrollen, treten wieder Leistungsprobleme auf.

Ich weiß, dass es keine gute Praxis ist, einen Link als Antwort bereitzustellen, aber die Beispiele, die sie bereitstellen, werden erklären, wie diese Bibliothek viel besser verwendet wird, als ich hier kann. Hoffentlich habe ich erklärt, warum große Listen schlecht sind, aber auch eine Lösung.

Resonanz
quelle
2
Update: Das Paket in dieser Antwort wird nicht verwaltet. Eine Gabel wird auf npmjs.com/package/react-infinite-scroller
Ali Al Amine
11

Erstens ist der Unterschied zwischen der Entwicklungs- und der Produktionsversion von React sehr groß, da in der Produktion viele umgangene Hygienekontrollen durchgeführt werden (z. B. Überprüfung der Requisitentypen).

Dann sollten Sie die Verwendung von Redux überdenken, da dies hier äußerst hilfreich für das ist, was Sie benötigen (oder für jede Art von Flussmittelimplementierung). Schauen Sie sich unbedingt diese Präsentation an: Big List High Performance React & Redux .

Bevor Sie jedoch in Redux eintauchen, müssen Sie einige Anpassungen an Ihrem React-Code vornehmen, indem Sie Ihre Komponenten in kleinere Komponenten aufteilen, da shouldComponentUpdatedas Rendern von Kindern vollständig umgangen wird. Dies ist also ein enormer Gewinn .

Wenn Sie detailliertere Komponenten haben, können Sie den Status mit Redux und React-Redux behandeln, um den Datenfluss besser zu organisieren.

Ich hatte kürzlich ein ähnliches Problem, als ich tausend Zeilen rendern und jede Zeile durch Bearbeiten ihres Inhalts ändern musste. Diese Mini-App zeigt eine Liste von Konzerten mit potenziellen Duplikaten an. Ich muss für jedes potenzielle Duplikat auswählen, ob ich das potenzielle Duplikat als Originalkonzert (kein Duplikat) markieren möchte, indem ich das Kontrollkästchen aktiviere und gegebenenfalls das bearbeite Name des Konzerts. Wenn ich für ein bestimmtes potenzielles doppeltes Element nichts unternehme, wird es als doppelt betrachtet und gelöscht.

So sieht es aus:

Geben Sie hier die Bildbeschreibung ein

Grundsätzlich gibt es 4 Netzkomponenten (hier gibt es nur eine Zeile, aber nur zum Beispiel):

Geben Sie hier die Bildbeschreibung ein

Hier ist der vollständige Code (funktionierender CodePen: Riesige Liste mit React & Redux ) unter Verwendung von Redux , React -Redux , unveränderlich , Neuauswahl und Neuzusammenstellung :

const initialState = Immutable.fromJS({ /* See codepen, this is a HUGE list */ })

const types = {
    CONCERTS_DEDUP_NAME_CHANGED: 'diggger/concertsDeduplication/CONCERTS_DEDUP_NAME_CHANGED',
    CONCERTS_DEDUP_CONCERT_TOGGLED: 'diggger/concertsDeduplication/CONCERTS_DEDUP_CONCERT_TOGGLED',
};

const changeName = (pk, name) => ({
    type: types.CONCERTS_DEDUP_NAME_CHANGED,
    pk,
    name
});

const toggleConcert = (pk, toggled) => ({
    type: types.CONCERTS_DEDUP_CONCERT_TOGGLED,
    pk,
    toggled
});


const reducer = (state = initialState, action = {}) => {
    switch (action.type) {
        case types.CONCERTS_DEDUP_NAME_CHANGED:
            return state
                .updateIn(['names', String(action.pk)], () => action.name)
                .set('_state', 'not_saved');
        case types.CONCERTS_DEDUP_CONCERT_TOGGLED:
            return state
                .updateIn(['concerts', String(action.pk)], () => action.toggled)
                .set('_state', 'not_saved');
        default:
            return state;
    }
};

/* configureStore */
const store = Redux.createStore(
    reducer,
    initialState
);

/* SELECTORS */

const getDuplicatesGroups = (state) => state.get('duplicatesGroups');

const getDuplicateGroup = (state, name) => state.getIn(['duplicatesGroups', name]);

const getConcerts = (state) => state.get('concerts');

const getNames = (state) => state.get('names');

const getConcertName = (state, pk) => getNames(state).get(String(pk));

const isConcertOriginal = (state, pk) => getConcerts(state).get(String(pk));

const getGroupNames = reselect.createSelector(
    getDuplicatesGroups,
    (duplicates) => duplicates.flip().toList()
);

const makeGetConcertName = () => reselect.createSelector(
    getConcertName,
    (name) => name
);

const makeIsConcertOriginal = () => reselect.createSelector(
    isConcertOriginal,
    (original) => original
);

const makeGetDuplicateGroup = () => reselect.createSelector(
    getDuplicateGroup,
    (duplicates) => duplicates
);



/* COMPONENTS */

const DuplicatessTableRow = Recompose.onlyUpdateForKeys(['name'])(({ name }) => {
    return (
        <tr>
            <td>{name}</td>
            <DuplicatesRowColumn name={name}/>
        </tr>
    )
});

const PureToggle = Recompose.onlyUpdateForKeys(['toggled'])(({ toggled, ...otherProps }) => (
    <input type="checkbox" defaultChecked={toggled} {...otherProps}/>
));


/* CONTAINERS */

let DuplicatesTable = ({ groups }) => {

    return (
        <div>
            <table className="pure-table pure-table-bordered">
                <thead>
                    <tr>
                        <th>{'Concert'}</th>
                        <th>{'Duplicates'}</th>
                    </tr>
                </thead>
                <tbody>
                    {groups.map(name => (
                        <DuplicatesTableRow key={name} name={name} />
                    ))}
                </tbody>
            </table>
        </div>
    )

};

DuplicatesTable.propTypes = {
    groups: React.PropTypes.instanceOf(Immutable.List),
};

DuplicatesTable = ReactRedux.connect(
    (state) => ({
        groups: getGroupNames(state),
    })
)(DuplicatesTable);


let DuplicatesRowColumn = ({ duplicates }) => (
    <td>
        <ul>
            {duplicates.map(d => (
                <DuplicateItem
                    key={d}
                    pk={d}/>
            ))}
        </ul>
    </td>
);

DuplicatessRowColumn.propTypes = {
    duplicates: React.PropTypes.arrayOf(
        React.PropTypes.string
    )
};

const makeMapStateToProps1 = (_, { name }) => {
    const getDuplicateGroup = makeGetDuplicateGroup();
    return (state) => ({
        duplicates: getDuplicateGroup(state, name)
    });
};

DuplicatesRowColumn = ReactRedux.connect(makeMapStateToProps1)(DuplicatesRowColumn);


let DuplicateItem = ({ pk, name, toggled, onToggle, onNameChange }) => {
    return (
        <li>
            <table>
                <tbody>
                    <tr>
                        <td>{ toggled ? <input type="text" value={name} onChange={(e) => onNameChange(pk, e.target.value)}/> : name }</td>
                        <td>
                            <PureToggle toggled={toggled} onChange={(e) => onToggle(pk, e.target.checked)}/>
                        </td>
                    </tr>
                </tbody>
            </table>
        </li>
    )
}

const makeMapStateToProps2 = (_, { pk }) => {
    const getConcertName = makeGetConcertName();
    const isConcertOriginal = makeIsConcertOriginal();

    return (state) => ({
        name: getConcertName(state, pk),
        toggled: isConcertOriginal(state, pk)
    });
};

DuplicateItem = ReactRedux.connect(
    makeMapStateToProps2,
    (dispatch) => ({
        onNameChange(pk, name) {
            dispatch(changeName(pk, name));
        },
        onToggle(pk, toggled) {
            dispatch(toggleConcert(pk, toggled));
        }
    })
)(DuplicateItem);


const App = () => (
    <div style={{ maxWidth: '1200px', margin: 'auto' }}>
        <DuplicatesTable />
    </div>
)

ReactDOM.render(
    <ReactRedux.Provider store={store}>
        <App/>
    </ReactRedux.Provider>,
    document.getElementById('app')
);

Lehren aus dieser Mini-App bei der Arbeit mit riesigen Datenmengen

  • Reaktionskomponenten funktionieren am besten, wenn sie klein gehalten werden
  • Die erneute Auswahl wird sehr nützlich, um eine Neuberechnung zu vermeiden und dasselbe Referenzobjekt (bei Verwendung von immutable.js) mit denselben Argumenten beizubehalten.
  • Erstellen Sie eine connectKomponente für eine Komponente, die den Daten am nächsten kommt, die sie benötigen, um zu vermeiden, dass die Komponente nur Requisiten weitergibt, die sie nicht verwenden
  • Die Verwendung der Fabric-Funktion zum Erstellen von mapDispatchToProps, wenn Sie nur die anfängliche Requisite benötigen, ownPropsist erforderlich, um unnötiges erneutes Rendern zu vermeiden
  • Reagieren & Redux definitiv zusammen rocken!
Pierre Criulanscy
quelle
2
Ich denke nicht, dass das Hinzufügen einer Abhängigkeit zu Redux notwendig ist, um das Problem des OP zu lösen. Weitere Dispatching-Aktionen zum Filtern seiner Ergebnismenge würden das Problem nur verschlimmern. Dispatches sind nicht so kostengünstig, wie Sie vielleicht denken, und behandeln diese spezielle Situation mit lokaler Komponente Zustand ist der effizienteste Ansatz
Deowk
4
  1. Reagieren Sie in der Entwicklungsversion auf Proptypen jeder Komponente, um den Entwicklungsprozess zu vereinfachen, während in der Produktion darauf verzichtet wird.

  2. Das Filtern der Liste von Zeichenfolgen ist für jede Eingabe sehr teuer. Dies kann zu Leistungsproblemen führen, da JavaScript nur einen Thread enthält. Die Lösung könnte darin bestehen, die Entprellungsmethode zu verwenden, um die Ausführung Ihrer Filterfunktion zu verzögern, bis die Verzögerung abgelaufen ist.

  3. Ein weiteres Problem könnte die riesige Liste selbst sein. Sie können ein virtuelles Layout erstellen und erstellte Elemente wiederverwenden, indem Sie nur Daten ersetzen. Grundsätzlich erstellen Sie eine scrollbare Containerkomponente mit fester Höhe, in die Sie den Listencontainer einfügen. Die Höhe des Listencontainers sollte abhängig von der Länge der sichtbaren Liste manuell festgelegt werden (itemHeight * numberOfItems), damit eine Bildlaufleiste funktioniert. Erstellen Sie dann einige Elementkomponenten, damit sie die Höhe des scrollbaren Containers ausfüllen, und fügen Sie möglicherweise ein oder zwei zusätzliche Nachahmungseffekte hinzu. Machen Sie sie zur absoluten Position und verschieben Sie beim Scrollen einfach ihre Position, damit sie eine fortlaufende Liste imitiert (ich denke, Sie werden herausfinden, wie Sie sie implementieren können :)

  4. Eine weitere Sache ist, dass das Schreiben in DOM auch eine teure Operation ist, insbesondere wenn Sie es falsch machen. Sie können die Leinwand zum Anzeigen von Listen verwenden und ein reibungsloses Bildlauferlebnis erzielen. Checkout-React-Canvas-Komponenten. Ich habe gehört, dass sie bereits einige Arbeiten an Listen durchgeführt haben.

AskarovBeknar
quelle
Irgendwelche Infos zu React in development? und warum nach Prototypen jeder Komponente suchen?
Liuuil
4

Schauen Sie sich React Virtualized Select an. Es wurde entwickelt, um dieses Problem zu beheben, und bietet meiner Erfahrung nach eine beeindruckende Leistung. Aus der Beschreibung:

HOC, das React-Virtualized und React-Select verwendet, um große Listen von Optionen in einem Dropdown-Menü anzuzeigen

https://github.com/bvaughn/react-virtualized-select

Madbreaks
quelle
4

Wie ich in meinem Kommentar erwähnt habe , bezweifle ich, dass Benutzer alle diese 10000 Ergebnisse gleichzeitig im Browser benötigen.

Was ist, wenn Sie durch die Ergebnisse blättern und immer nur eine Liste mit 10 Ergebnissen anzeigen?

Ich habe mit dieser Technik ein Beispiel erstellt , ohne eine andere Bibliothek wie Redux zu verwenden. Derzeit nur mit Tastaturnavigation, kann aber problemlos erweitert werden, um auch beim Scrollen zu arbeiten.

Das Beispiel besteht aus 3 Komponenten, der Containeranwendung, einer Suchkomponente und einer Listenkomponente. Fast die gesamte Logik wurde in die Containerkomponente verschoben.

Das Wesentliche liegt darin, startdas selectedErgebnis zu verfolgen und die Interaktion mit der Tastatur zu verschieben.

nextResult: function() {
  var selected = this.state.selected + 1
  var start = this.state.start
  if(selected >= start + this.props.limit) {
    ++start
  }
  if(selected + start < this.state.results.length) {
    this.setState({selected: selected, start: start})
  }
},

prevResult: function() {
  var selected = this.state.selected - 1
  var start = this.state.start
  if(selected < start) {
    --start
  }
  if(selected + start >= 0) {
    this.setState({selected: selected, start: start})
  }
},

Während Sie einfach alle Dateien durch einen Filter leiten:

updateResults: function() {
  var results = this.props.files.filter(function(file){
    return file.file.indexOf(this.state.query) > -1
  }, this)

  this.setState({
    results: results
  });
},

Und die Ergebnisse basierend auf startund limitin der renderMethode aufteilen:

render: function() {
  var files = this.state.results.slice(this.state.start, this.state.start + this.props.limit)
  return (
    <div>
      <Search onSearch={this.onSearch} onKeyDown={this.onKeyDown} />
      <List files={files} selected={this.state.selected - this.state.start} />
    </div>
  )
}

Geige mit einem voll funktionsfähigen Beispiel: https://jsfiddle.net/koenpunt/hm1xnpqk/

Koen.
quelle
3

Versuchen Sie es mit einem Filter, bevor Sie ihn in die React-Komponente laden. Zeigen Sie nur eine angemessene Anzahl von Elementen in der Komponente an und laden Sie bei Bedarf mehr. Niemand kann so viele Elemente gleichzeitig anzeigen.

Ich glaube nicht, dass Sie es sind, aber verwenden Sie keine Indizes als Schlüssel .

Um herauszufinden, warum die Entwicklungs- und Produktionsversionen unterschiedlich sind, können Sie profilingIhren Code ausprobieren .

Laden Sie Ihre Seite, starten Sie die Aufnahme, führen Sie eine Änderung durch, beenden Sie die Aufnahme und überprüfen Sie die Timings. Sehen Sie hier , um Anweisungen für Leistungsprofil in Chrome .

RationalDev mag GoFundMonica
quelle
2

Für alle, die mit diesem Problem zu kämpfen haben, habe ich eine Komponente geschrieben react-big-list , die Listen mit bis zu 1 Million Datensätzen verarbeitet.

Darüber hinaus bietet es einige ausgefallene Zusatzfunktionen wie:

  • Sortierung
  • Caching
  • Benutzerdefinierte Filterung
  • ...

Wir verwenden es in der Produktion in einigen Apps und es funktioniert großartig.

Meemaw
quelle