简体   繁体   English

ReactJS中的非阻塞渲染

[英]Non blocking render in ReactJS

I'm learning ReactJS and trying to build some application on it. 我正在学习ReactJS并尝试在其上构建一些应用程序。

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 components become huge. 当我试图修改我的状态并进行渲染时,我的页面会冻结,并且在我的组件变得庞大时渲染完成之前无法执行任何操作。

I found that I can use shouldComponentUpdate to optimize my code, but the question comes to me is: Can I make this render procedure be non blocking? 我发现我可以使用shouldComponentUpdate来优化我的代码,但问题是:我能否使这个渲染过程无阻塞? 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? 或者,如果用户可以取消渲染,例如,对于实时编辑器,如果用户编辑编辑器的内容,“预览”部分将停止渲染旧内容并尝试渲染新内容而不阻止编辑器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.com/ajax/libs/react/15.0.1/react.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.js"></script> <script src="https://cdnjs.cloudflare.com/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. 当我按下“ Start ,页面将冻结,并且在呈现所有Box之前不会响应。 Is it possible to add a button named Cancel which user can cancel the render and clear all boxes? 是否可以添加一个名为Cancel的按钮,用户可以取消渲染并清除所有框?

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. 这是一个很好的问题,也是setTimeout的完美用例,它可以安排更新到下一轮事件循环。

Rather than store the number of components to render, store an array of components, and render them directly. 而不是存储要渲染的组件数,而是存储组件数组,并直接呈现它们。 jsfiddle 的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 如果要提高速度,可以按每个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 component doesn't block and you could easily throw a loading spinner up there. 在10,000个批次中,基本的盒子组件不会阻塞,您可以轻松地将装载旋转器放在那里。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM