title: React display n number of elements on page and keep the rest idle
body: <p>I am creating a react app and I want to only show 21 number of elements at a time while keeping the rest in idle. When the user scrolls to the bottom of the page, show another 21 elements, and repeat this process until all the elements are visible.</p>
  
  <p>I have my function <code>_injectAdsInList</code>  that gets the products and inserts an add every 20 products this works but when I want to only show 21 elements at a time (20 products and 1 add) while keeping the rest idle to load another 21 elements when they scroll down I get an error on the screen and in my console doing a console log my array <code>displayedList</code> is coming back as <code>undefined</code>.  </p>
  
  <p>This is my component.</p>
  
  <pre><code>    import React from "react";
  import { Loading } from "./LoadingComponent";
  
  const axios = require('axios');
  
  class Products extends React.Component {
  
  
    constructor(props){
          super(props);
          this.state = {
        displayedList : [],
        indexDisplayed : 0,
        isLoading: false,
        error: null
      }
      }
  
  
  
    _injectAdsInList = list =&gt; {
      // an array of your ads
  
      this.setState({ isLoading: false });
      const AdsList = ['111','2222'];
  
      let displayedList = this.state.displayedList;
      let indexDisplayed = this.state.displayedList;
  
      if (Array.isArray(list)) {
        const insertAdAt = 21;
  
        const productsAndAdsList = list.map((item, index) =&gt; {
          // not sure about this calculation
          // but this should be done here
  
          if (index % insertAdAt === 0 &amp;&amp; index !== 0) {
            // its the 20th item insert an ad
            return AdsList[0];
          }
  
          // otherwise insert the item
  
  
          return item;
  
  
  
          });
  
  
          for(let i = indexDisplayed +1; i &lt;= indexDisplayed + 21; i++ ){
           displayedList.push(productsAndAdsList[i]);
          }
  
  
  
  
  
  
        this.setState({productsAndAdsList});
  
  
  
      }
    };
  
  
  
  
  
    _getProducts = () =&gt; {
  
      this.setState({ isLoading: true });
  
      axios.get('http://localhost:3000/products').then(list =&gt; this._injectAdsInList(list.data))
        .catch(error =&gt; this.setState({ error, isLoading: false }));
    };
  
    _addToDisplay = ()=&gt; {
  
      let displayedList = this.state.displayedList;
      let indexDisplayed = this.state.displayedList;
      let productsAndAdsList = this.state.displayedList;
          for(let i = indexDisplayed +1 ; i &lt;= indexDisplayed + 21; i++ ){
              displayedList.push(productsAndAdsList[i]);
          }
  
          this.setState({
              indexDisplayed : this.state.indexDisplayed+21, displayedList : displayedList }, ()=&gt;{console.log(this.state.displayedList)
          });
      }
  
  
    _sortPrice = () =&gt; {
      const { displayedList } = this.state;
  
      const sortedProducts = displayedList.sort((a, b) =&gt; a.price - b.price);
      this.setState({ displayedList: sortedProducts });
    };
  
    _sortSize = () =&gt; {
      const { displayedList } = this.state;
  
      const sortedProducts = displayedList.sort((a, b) =&gt; a.size - b.size);
      this.setState({ displayedList: sortedProducts });
    };
  
    _sortId = () =&gt; {
      const { displayedList } = this.state;  
      const sortedProducts =  displayedList.sort((a, b) =&gt; {
    if (a.id &lt; b.id)
      return -1;
    if (a.id &gt; b.id)
      return 1;
    return 0;
  });
      this.setState({ displayedList: sortedProducts });
    }
  
     _timeAgo = (prevDate) =&gt; {
          const diff = Number(new Date()) - prevDate;
          const minute = 60 * 1000;
          const hour = minute * 60;
          const day = hour * 24;
          const month = day * 30;
          const year = day * 365;
          switch (true) {
              case diff &lt; minute:
                  const seconds = Math.round(diff / 1000);
                   return `${seconds} ${seconds &gt; 1 ? 'seconds' : 'second'} ago`
              case diff &lt; hour:
                  return Math.round(diff / minute) + ' minutes ago';
              case diff &lt; day:
                  return Math.round(diff / hour) + ' hours ago';
              case diff &lt; month:
                  return Math.round(diff / day) + ' days ago';
              case diff &lt; year:
                  return Math.round(diff / month) + ' months ago';
              case diff &gt; year:
                  return Math.round(diff / year) + ' years ago';
              default:
                  return "";
          }
      };
  
    componentDidMount() {
  
      this._getProducts();
    }
  
    render() {
  
      const { displayedList, isLoading, hasError } = this.state;
  
  console.log(this.state.displayedList);
  
      // show spinner
      if (!hasError &amp;&amp; isLoading) {
        return &lt;Loading /&gt;;
      }
  
      // show error
      if (hasError &amp;&amp; !isLoading) {
        return &lt;p&gt;error.message&lt;/p&gt;;
      }
  
      return (
        &lt;div&gt;
         &lt;div className="row"&gt;
              &lt;div className="col-12"&gt;
                  &lt;button onClick={this._sortPrice}&gt;sort by price lower to higher&lt;/button&gt;
                  &lt;button onClick={this._sortSize}&gt;sort by size small to big&lt;/button&gt;
                  &lt;button onClick={this._sortId}&gt;sort by Id&lt;/button&gt;  
              &lt;/div&gt;  
          &lt;/div&gt;
          { displayedList.map(item =&gt; { return (
                          &lt;div className="row"&gt;
                &lt;div className="col-4"&gt;
                  &lt;p&gt; Price: ${(item.price / 100).toFixed(2)}&lt;/p&gt;
                &lt;/div&gt;
  
                &lt;div className="col-4"&gt;
                  &lt;p style={{ fontSize: `${item.size}px` }}&gt; {item.face}&lt;/p&gt;
                &lt;/div&gt;
              &lt;div className="col-3"&gt;
                    &lt;p&gt;Published: {this._timeAgo(new Date(item.date).getTime())}&lt;/p&gt;
                  &lt;/div&gt;
              &lt;/div&gt;
              ) } )
  
                  }
  
  
  
         &lt;div className="row"&gt;
              &lt;div className="col-12"&gt;
                  &lt;p&gt;END OF CATALOG&lt;/p&gt;  
              &lt;/div&gt;  
          &lt;/div&gt;
        &lt;/div&gt;
      );
    }
  }
  
  export default Products;
  </code></pre>
  
  <p>This is my error.</p>
  
  <pre><code>  TypeError: Cannot read property 'price' of undefined
  </code></pre>
  
  <p>This is my original data from database</p>
  
  <pre><code> {
      "id": "29470-8qkpkhuqdct",
      "size": 15,
      "price": 999,
      "face": "( .-. )",
      "date": "Tue Nov 05 2019 20:29:01 GMT-0500 (Colombia Standard Time)"
    },
    {
      "id": "38405-fq66zcem9a5",
      "size": 27,
      "price": 787,
      "face": "( .o.)",
      "date": "Thu Nov 07 2019 13:32:17 GMT-0500 (Colombia Standard Time)"
    },
    {
      "id": "21765-r5f5rctbs6i",
      "size": 24,
      "price": 619,
      "face": "( `·´ )",
      "date": "Mon Nov 11 2019 20:57:19 GMT-0500 (Colombia Standard Time)"
    },
    {
      "id": "82780-5sypj693ojx",
      "size": 26,
      "price": 994,
      "face": "( ° ͜ ʖ °)",
      "date": "Fri Nov 15 2019 12:20:46 GMT-0500 (Colombia Standard Time)"
    },    
  </code></pre>
  
  <p>This is what I get in my console log repeated 4 times</p>
  
  <p>[]
  0: {id: "71853-4k9d13grmxj", size: 19, price: 4, face: "( .o.)", date: "Thu Nov 21 2019 11:06:00 GMT-0500 (Colombia Standard Time)"}
  length: 1
  <strong>proto</strong>: Array(0)</p>