ReactJS中的非阻塞渲染 [英] Non blocking render in ReactJS

查看:99
本文介绍了ReactJS中的非阻塞渲染的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习ReactJS并尝试在其上构建一些应用程序。

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 components become huge.

我发现我可以使用 shouldComponentUpdate 优化我的代码,但问题是:我可以使这个渲染过程无阻塞吗?所以我可以告诉用户该页面正在处理一些繁重的加载执行,请等待或者显示执行的进度?或者,如果用户可以取消渲染,例如,对于实时编辑器,如果用户编辑编辑器的内容,预览部分将停止渲染旧内容并尝试渲染新内容而不阻止编辑器UI?

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? 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?

这是重载示例代码:

<!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>

当我按开始,在呈现所有 Box 之前,页面将冻结并且无响应。是否可以添加一个名为取消的按钮,哪个用户可以取消渲染并清除所有框?

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?

推荐答案

这是一个很好的问题,也是 setTimeout 的完美用例,它可以安排更新到下一轮的事件循环。

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.

不是存储要渲染的组件数,而是存储组件数组并直接渲染它们。 jsfiddle

Rather than store the number of components to render, store an array of components, 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>
      )
    }
  })

更新:

如果你只想在数组填满后显示状态up,在达到那个尺寸之前不要显示任何东西:

这不起作用:

{ 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>

如果你想提高速度,你可以按每项目推送超过setTimeout

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)
})

更新小提琴。我认为这类问题需要时间才能完成。在10,000个批次中,基本的盒子组件不会阻塞,你可以很容易地在那里抛出一个加载微调器。

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.

这篇关于ReactJS中的非阻塞渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆