title: How do you incrementally update a list in React?
body: <p>I posted an <a href="https://stackoverflow.com/questions/65452961/my-react-list-item-components-dont-render-one-at-a-time">earlier question</a> about this, but have not had any luck finding a solution, and seeing behavior I don't understand. I've reworked the code a bit and will explain some of the things I tried.</p>
  <p><strong>The problem</strong>
  I want to display a list of prime numbers as they are generated. First of all, here's a test function that behaves correctly:</p>
  <pre class="lang-js prettyprint-override"><code>const testPrimes = (primes, setPrimes) =&gt; {
    const tPrimes = [3, 5, 7];
  
    for (const [i, p] of tPrimes.entries()) {
      setTimeout(() =&gt; {
        setPrimes((oldPrimes) =&gt;
          oldPrimes.concat(&lt;Response {...{ prime: p, key: p }} /&gt;)
        );
      }, i * 1000);
    }
  };
  </code></pre>
  <p>And this is called like so:</p>
  <pre class="lang-js prettyprint-override"><code>
  export default ({ args, appState }) =&gt; {
    const [primes, setPrimes] = useState([]);
  
    useEffect(() =&gt; {
      testPrimes(setPrimes);
    }, []);
  
    return (
      &lt;div&gt;
        &lt;div className=&quot;row&quot;&gt;{primes}&lt;/div&gt;
      &lt;/div&gt;
    );
  };
  </code></pre>
  <p>This displays each prime in the list at one second intervals, which is the desired behavior.</p>
  <p>In the &quot;real&quot; program, I use a generator function instead of an array:</p>
  <pre class="lang-js prettyprint-override"><code>
  const testPrimes3 = (args, setPrimes) =&gt; {
    const gen = fPrimes({ args });
  
    let i = 0;
    for (const p of gen) {
      console.log(&quot;foo&quot;);
      setTimeout(() =&gt; {
        setPrimes((oldPrimes) =&gt;
          oldPrimes.concat(&lt;Response {...{ prime: p, key: p }} /&gt;)
        );
      }, 100);
    }
  };
  </code></pre>
  <p>The <code>testPrime3</code> function is called similar to <code>testPrime</code> above (see below);</p>
  <p>When testPrime3 is called, I see 'foo' displayed 3 times in the console, with time intervals between each, but the list in React gets populated all at once when the generator completes, instead of incrementally for each prime yielded.</p>
  <p>I've tried wrapping the setEffect call to the generator in a setTimeout, but that has no effect; here's the call with the setTimeout commented out:</p>
  <pre><code>  useEffect(() =&gt; {
      // setTimeout(() =&gt;
      testPrimes3(args, setPrimes);
      // , 1000);
    }, []);
  </code></pre>
  <p>Is there a better way to control the incremental rendering of elements in the list other than through a setState call?</p>
  <hr />
  <p><strong>update</strong>
  It was suggested to not add an element to <code>primes</code>, but render it in the component instead:</p>
  <pre class="lang-js prettyprint-override"><code>const testPrimes3 = (args, setPrimes) =&gt; {
    const gen = fPrimes({ args });
  
    let i = 0;
    for (const p of gen) {
      console.log(&quot;foo&quot;);
      setTimeout(() =&gt; {
        setPrimes((oldPrimes) =&gt; oldPrimes.concat(p));
      }, 100);
    }
  };
  
  [...]
    return (
      &lt;div&gt;
        &lt;div className=&quot;row&quot;&gt;
          {primes.map((p) =&gt; (
            &lt;Response {...{ prime: p, key: p }} /&gt;
          ))}
        &lt;/div&gt;
      &lt;/div&gt;
    );
  </code></pre>
  <p>This has no effect.</p>