React extremely slow when iterating through JSON

Question!

So, Im trying to fetch an JSON API with fetch() and iterate through it and render it in Reactjs. It does actually work pretty well with small json lists up to 100 items. But when I try the same thing with a json list of 900 items and upwards, it takes quite a while and the entire site isnt responsive anymore and gets pretty slow.

So what am I doing wrong here and what can I fix to make the site faster?

API.js

import _ from 'lodash/array';    
const baseURL = 'https://url.com/api/v1';
class API {
  static getLibrary(user, callback) {
    fetch(`${baseURL}/users/${user}/library`, {
      method: 'get',
      headers: { 'Content-type': 'application/json' },
    })
    .then((response) => {
      response.json().then((data) => {
        const titles = [];
        const status = [];
        const covers = [];
        const url = [];
        const rating = [];
        const episodesWatched = [];
        const episodesMax = [];
        for (const item in data) {
          titles.push(data[item].library.title);
          status.push(data[item].status);
          covers.push(data[item].library.cover_image);
          url.push(data[item].library.url);
          rating.push(data[item].rating);
          episodesWatched.push(data[item].episodes_watched);
          episodesMax.push(data[item].library.episode_count);
        }
        const library = _.zip(
          titles,
          covers,
          url,
          rating,
          episodesWatched,
          episodesMax
        );
        callback(library);
      });
    });
  }
}
export default API;

Index.jsx:

import React from 'react';
import API from '../modules/api';
import { Grid, Row, Col } from 'react-flexgrid';
import Blazy from 'blazy';
import _ from 'lodash/collection';

class Library extends React.Component {
  constructor() {
    super();
    this.state = {
      library: undefined,
    };
  }

  componentDidMount() {
    API.getLibrary(this.props.params.user, (list) => {
      this.setState({
        library: _.sortBy(list, 0),
      });
    });
  }
  render() {
    var bLazy = new Blazy();
    if (this.state.library) {
      return (
        <div className="content">
          <Grid>
            <Row>
            {this.state.library.map(function(entry, index) {
              return (
                <Col key={index} xs={6} md={2}>
                  <Card>
                    <CardTitle>{entry[0]}</CardTitle>
                  </Card>
                </Col>
                );
            })}
            </Row>
          </Grid>
        </div>
      );
    }
    return (
      <div>
        Loading
      </div>
    );
  }
}

export default Library;
By : FirstZer0


Answers

Rendering 900 items even directly in the DOM with element.innerHTML can be slow. So you might want to a use a list implementation like this one https://github.com/seatgeek/react-infinite which would load things into the DOM as you scroll.

Also when you assign key={index} it is a good practice to use unique keys, otherwise React would be confused in case you would reorder or change your list at some point



It's not clear from the code provided where the issue is. Possible culprits:

  • Your post-processing logic (_.zip, _.sortBy) is slow, and causes the UI to lock. I'd start by timing these operations and seeing whether they represent a significant bottleneck.

  • You end up with a large number of DOM elements, and this causes the page to appear sluggish. There are various ways to fix this, but pagination or infinite scroll are good top-of-mind approaches. You might try FixedDataTable for a good lazy-rendering implementation for large data tables.



This video can help you solving your question :)
By: admin