title: Why does my React app use so much memory?
body: <p>So, I have been experimenting with ReactJS and I have been testing its performance when loading lots of data, and I have noticed it to be quite taxing. In particular, I noticed that after my demo application loads a few thousand rows, it starts to use hundreds of megabytes. Left long enough, at about 10,000 rows, it will surpass a gigabyte of RAM used.</p>
  
  <blockquote>
    <p>Edit: I believe the high RAM usage was caused by having the React DevTools window open. It seems that using that significantly increased how much RAM is being used. However, without it open, it will still use a few hundred MB (up to 500MB, as low as 350MB) which I believe is quite a lot for just a big list.</p>
  </blockquote>
  
  <ul>
  <li>What is it about this app that makes it so demanding?</li>
  <li>Why is React updating the entire List when adding new rows (as shown by the React DevTools "Highlight Updates" feature)?</li>
  <li>What can I do to keep RAM usage low, without locking up the browser while everything loads?</li>
  </ul>
  
  <p>I have provided my app below. It is entirely self-contained, so just create a file (index.html or whatever) and put all this text in it, and run the file (or optionally host it on a web server to have access to the React DevTools).</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
  &lt;head&gt;
  &lt;meta charset="utf-8"&gt;
  &lt;title&gt;React&lt;/title&gt;
  &lt;script src="https://unpkg.com/babel-standalone@6/babel.min.js"&gt;&lt;/script&gt;
  &lt;script src="https://unpkg.com/react@15/dist/react.min.js"&gt;&lt;/script&gt;
  &lt;script src="https://unpkg.com/react-dom@15/dist/react-dom.min.js"&gt;&lt;/script&gt;
  &lt;link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"&gt;
  &lt;style&gt;
  ol {
      margin-left: 50px;
      list-style-type: none;
  }
  p { display: inline; }
  img {height: 1em; }
  
  
  &lt;/style&gt;
  &lt;script type="text/babel"&gt;
  
  class ListItem extends React.Component {
      render() {
          return(&lt;li&gt;&lt;p&gt;{this.props.index}.&lt;/p&gt;&amp;nbsp;&lt;input type="checkbox" /&gt;&lt;img src="http://www.tastyislandhawaii.com/images/spam_musubi/spam_can_open.jpg" /&gt;&lt;a href="#"&gt;HELLO I AM SPAM NICE TO MEET YOU&lt;/a&gt;&lt;/li&gt;);
      }
  }
  
  class List extends React.Component {
  
      constructor(props) {
          super(props);
          this.state = {
              TICK_INTERVAL: 500,
              ROWS_PER_TICK: 100,
              adding: false,
              list: [],
              total: 0,
              count: 0
          };
  
          this.start = this.start.bind(this);
          this.stop = this.stop.bind(this);
          this.addMore = this.addMore.bind(this);
      }
  
      start() {
          console.log("starting adding");
          this.setState({adding: true, total: 20000});
          setTimeout(this.addMore, this.state.TICK_INTERVAL);
      }
  
      stop() {
          console.log("stopping adding");
          this.setState({adding: false, total: 0});
      }
  
      addMore() {
          console.log("adding more...", this.state.adding);
          let tempCount = this.state.count;
          let tempList = [];
          for (let temp = 0; tempCount &lt; this.state.total &amp;&amp; temp &lt; this.state.ROWS_PER_TICK &amp;&amp; this.state.adding; temp++) {
              tempList.push(&lt;ListItem key={tempCount} index={tempCount}/&gt;);
              tempCount++;
          }
          this.setState({list: this.state.list.concat(tempList), count: tempCount});
          if (this.state.count &lt; this.state.total) {
              if (this.state.adding) {
                  setTimeout(this.addMore, this.state.TICK_INTERVAL);
              }
          } else {
              this.setState({adding: false});
          }
      }
  
      render() {
          let button;
          if (this.state.adding) {
              button = &lt;button type="Submit" className="btn btn-danger" onClick={this.stop}&gt;HALT!&lt;/button&gt;
          } else {
              button = &lt;button type="Submit" className="btn btn-success" onClick={this.start}&gt;BOOM!&lt;/button&gt;
          }
  
          return(&lt;div&gt;{button}&lt;ol&gt;{this.state.list}&lt;/ol&gt;&lt;/div&gt;);
      }
  }
  
  ReactDOM.render(&lt;List/&gt;, document.getElementById("root"));
  &lt;/script&gt;
  &lt;/head&gt;
  &lt;body&gt;&lt;div id="root"&gt;&lt;/div&gt;&lt;/body&gt;
  &lt;/html&gt;
  </code></pre>