最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Non blocking render in ReactJS - Stack Overflow

programmeradmin0浏览0评论

I'm learning ReactJS and trying to build some application on it.

When I'm trying to modify my state and render, my page is freezing and can't do anything until the render is finished when my ponents bee huge.

I found that I can use shouldComponentUpdate to optimize my code, but the question es to me is: Can I make this render procedure be non blocking? And so I can tell the user that the page is processing some heavy loading executions and please wait or maybe show the progress of the execution? Or if the user can cancel the render, for example, for a live editor, if user edit the content of the editor, the "preview" section will stop rendering old content and trying to render new content without blocking the editor UI?

Here's the heavy loading example code:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>React Tutorial</title>
    <script src=".0.1/react.js"></script>
    <script src=".0.1/react-dom.js"></script>
    <script src=".8.24/browser.js"></script>
    <script src=".2.0/jquery.min.js"></script>
  </head>
  <body>
    <div id="content"></div>
    <script type="text/babel">
      var Box = React.createClass({
        render: function() {
          return (
            <div>Box</div>
          );
        }
      });
      
      var CommentBox = React.createClass({
        getInitialState: function() {
          return {box_count: 5};
        },
        
        heavyLoadRender: function() {
          this.setState({box_count: 40000});
        },
        
        render: function() {
          var render_box = [];
          for (var i=0; i<this.state.box_count; i++) {
            render_box.push(<Box />);
          }
          return (
            <div>
              {render_box}
              <button onClick={this.heavyLoadRender}>Start</button>
            </div>
          );
        }
      });
      
      ReactDOM.render(
        <CommentBox />,
        document.getElementById('content')
      );
    </script>
  </body>
</html>

I'm learning ReactJS and trying to build some application on it.

When I'm trying to modify my state and render, my page is freezing and can't do anything until the render is finished when my ponents bee huge.

I found that I can use shouldComponentUpdate to optimize my code, but the question es to me is: Can I make this render procedure be non blocking? And so I can tell the user that the page is processing some heavy loading executions and please wait or maybe show the progress of the execution? Or if the user can cancel the render, for example, for a live editor, if user edit the content of the editor, the "preview" section will stop rendering old content and trying to render new content without blocking the editor UI?

Here's the heavy loading example code:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>React Tutorial</title>
    <script src="https://cdnjs.cloudflare./ajax/libs/react/15.0.1/react.js"></script>
    <script src="https://cdnjs.cloudflare./ajax/libs/react/15.0.1/react-dom.js"></script>
    <script src="https://cdnjs.cloudflare./ajax/libs/babel-core/5.8.24/browser.js"></script>
    <script src="https://cdnjs.cloudflare./ajax/libs/jquery/2.2.0/jquery.min.js"></script>
  </head>
  <body>
    <div id="content"></div>
    <script type="text/babel">
      var Box = React.createClass({
        render: function() {
          return (
            <div>Box</div>
          );
        }
      });
      
      var CommentBox = React.createClass({
        getInitialState: function() {
          return {box_count: 5};
        },
        
        heavyLoadRender: function() {
          this.setState({box_count: 40000});
        },
        
        render: function() {
          var render_box = [];
          for (var i=0; i<this.state.box_count; i++) {
            render_box.push(<Box />);
          }
          return (
            <div>
              {render_box}
              <button onClick={this.heavyLoadRender}>Start</button>
            </div>
          );
        }
      });
      
      ReactDOM.render(
        <CommentBox />,
        document.getElementById('content')
      );
    </script>
  </body>
</html>

When I press Start, the page will freeze and no response until all Box is rendered. Is it possible to add a button named Cancel which user can cancel the render and clear all boxes?

Share Improve this question asked Apr 19, 2016 at 4:43 NierNier 6588 silver badges15 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 8

This is a great question, and a perfect use case for setTimeout which can schedule an update to the next round of the event loop.

Rather than store the number of ponents to render, store an array of ponents, and render them directly. jsfiddle

 var CommentBox = React.createClass({
    getInitialState: function() {
      return { boxes: [<Box key="first" />] };
    },

    heavyLoadRender: function() {
      setTimeout(() => {
        if (this.state.boxes.length < 50000) {
          this.setState({ 
            boxes: this.state.boxes.concat(<Box key={this.state.boxes.length} />)
          })
          this.heavyLoadRender()
        }
      })
    },

    render: function() {
      return (
        <div>
          <button onClick={this.heavyLoadRender}>Start</button>
          {this.state.boxes}
        </div>
      )
    }
  })

Update:

If you only want to show the state once the array is filled up, don't display anything until it hits that size:

This did not work:

{ this.state.boxes.length === 50000 && this.state.boxes }

Hope is not lost though! Use style!

<div style={{ display: this.state.boxes.length === 50000 ? 'block' : 'none' }}>
  { this.state.boxes }
</div>

If you want to increase the speed, you can push more than item per setTimeout

var newBoxes = []
for (var i = 0; i < 5; i++) {
   newBoxes.push(<Box />)
}
this.setState({ 
  boxes: this.state.boxes.concat(newBoxes)
})

updated fiddle. I think this whole class of problems is going to take time to perform. In batches of 10,000 the basic box ponent doesn't block and you could easily throw a loading spinner up there.

发布评论

评论列表(0)

  1. 暂无评论