title: How to concurrently load and render data one by one
body: <p>I want to find a way to fill up a table with data that I load at the press of a button. The data is loaded by processing a bunch of files. Each item of data takes about a quarter of a second to load.</p>
  
  <p>Currently, I'm using a functional component for the whole page and hooks for state. I would like to load and render the data one by one, but when I (the user) begin loading, the app freezes and I cannot click away to even X out the app. After loading, however, the app resumes with the collected data.</p>
  
  <p>I've tried a few different solutions, and I'll detail the reasons each of them fail.</p>
  
  <p><b>Suspense or lazy loading:</b>
  The idea is to load the next item as soon as it's ready. These solutions require that all the data is rendered at the same time once it is all loaded. I'm looking for a way to render each item one at a time as they are loaded.</p>
  
  <p><b>Generators/Callbacks:</b>
  When the button is clicked and the function for loading data is begun, the app freezes until all data is loaded.</p>
  
  <p><b>Promises:</b>
  I could be using it wrong. I'm under the impression that each item would require a separate promise. I'll then have to use one of the solutions above for the whole.</p>
  
  <p><b>React useEffect:</b>
  Not sure how this could help the state update and re-render with each callback.</p>
  
  <pre><code>export function loadTheData(callback) {
    for (const file of getFiles()) {
      callback(file);
    }
  }
  </code></pre>
  
  <p>getFiles is a generator function.</p>
  
  <pre class="lang-js prettyprint-override"><code>import React, { useState, useReducer, useCallback, useEffect } from 'react';
  import { Button } from '@blueprintjs/core';
  import { loadTheData} from '../../actions/data';
  import Page from '../common/Page';
  
  export default function MyComp() {
  
    const [data, setData] = useState([]);
    const [isLoading, setIsLoading] = useState(false);
  
    function loadData() {
      if (isLoading) {
        return;
      }
      setIsLoading(true);
  
      loadTheData(item =&gt; { // loadTheData is an external function
        setData(prevData =&gt; [...prevData, item]);
      });
      setIsLoading(false);
    }
  
    return (
      &lt;Page&gt;
        &lt;Button
          onClick={loadData}
          loading={isLoading}
        /&gt;
        &lt;p&gt;{data.length}&lt;/p&gt;
      &lt;/Page&gt;
    );
  }
  </code></pre>
  
  <p>I expect the data.length value to increase one by one until it's complete after I press the button, but instead it is frozen at 0 until the end when it changes to the correct data length. The loadTheData function provides the data one at a time into the callback function. I know the loadTheData function and other parts of the code work properly. I'm just not sure how to go about concurrently/asynchronously loading <em>and</em> rendering the data that is loaded.</p>