ReactJS 中的非阻塞渲染

IT技术 javascript reactjs
2021-05-21 23:35:49

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

当我尝试修改我的状态和渲染时,我的页面冻结并且无法执行任何操作,直到我的组件变得巨大时渲染完成。

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

当我按下 时Start,页面将冻结并且在所有内容Box都呈现之前没有响应是否可以添加一个名为Cancel哪个用户可以取消渲染并清除所有框的按钮?

1个回答

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

不是存储要渲染的组件数量,而是存储组件数组,然后直接渲染它们。提琴手

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

更新:

如果您只想在数组填满后显示状态,请在达到该大小之前不要显示任何内容:

这不起作用:

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

希望并没有失去!使用风格!

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

如果你想提高速度,你可以推动多个项目 setTimeout

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

更新小提琴我认为这整类问题都需要时间来解决。批量为 10,000 个时,基本框组件不会阻塞,您可以轻松地将加载微调器放在那里。