在DOM渲染时,React显示加载微调器

时间:2015-05-19 13:53:06

标签: reactjs

我有一个列表,其中包含首先加载30个项目的项目,如果用户点击"全部加载",则会显示其余项目:

+---------------------------------------------------------+
|                                                         |
|                           List                          |
|                                                         |
|                                                         |
|                                                         |
+---------------------------------------------------------+
|                       Load All Button                   |
+---------------------------------------------------------+

当列表很大(超过1K项)时,"加载全部"步骤需要一些时间,同时DOM被卡住而没有响应。

利用React的生命周期事件的正确方法是什么,以便点击按钮后它将变为加载微调器,当列表完全呈现并准备就绪后它会改回来?

我尝试将两个部分(列表和按钮)分成两个组件,然后将它们包装在一个包含" loading"的父组件中。然后更改列表componentDidUpdate功能中的状态,但它没有工作

的jsfiddle

package lubridate

2 个答案:

答案 0 :(得分:8)

React中的渲染是同步的,这意味着没有任何东西可以与它一起运行。

您可以逐步呈现列表,因为用户的屏幕可能无法一次显示超过100个项目。

另外,请注意,在开发构建中渲染数千个项目比在React的生成构建中慢得多。

编辑:另一种选择是首先渲染加载器,然后在下一帧渲染列表项。将显示加载程序,直到列表项完成呈现。

React.createClass({
    getInitialState: function() {
        return {
            loading: false,
            showAll: false,
        };
    },

    _showAll: function() {
        this.setState({ showAll: true, loading: true }, function() {
            // Using setTimeout here ensures that the component will wait until
            // the next frame before trying to render again.
            this.setTimeout(function() {
                this.setState({ loading: false });
            }.bind(this), 1000 / 60);
        });
    },

    render: function() {
        var amount = (this.state.showAll && !this.state.loading) ? 100000 : 3;
        return (
            <div>
                <button onClick={this._showAll}>
                    {this.state.loading ? 'Loading...' : 'Show all'}
                </button>
                {items.slice(0, amount).map(renderItem)}
            </div>
        );
    },
});

答案 1 :(得分:0)

这是一个简单的类,其中包含更新的React 16示例(为清晰起见,使用内联注释):

class People extends Component {
   state = {
      rows: [],
      loaded: false
   }
   /* lifecycle hook - keeping mind we are manipulating the DOM */
   /* within the component so we need to know the component/dom is ready */
   componentDidMount(){
      let self = this;
      /* returns a fetch() call stored in context passed down */
      /* through a higher order component */
      this.props.context.getPeople() 
        .then(json => { self.setState({rows:json.rows, loaded: true}); })
        /* Notice that loaded is set to true in the state object */
   }

   loading = () => (
      <div className={this.state.loaded?'ajax-loaded':'ajax-loading'}>LOADING</div>
      /* The class ajax-loaded -- you guessed it, hides the div */
      /* The thing to always keep in mind -- when state changes, things happen! */
   );
   render() {
       return (
           <div>
               {this.loading()}
               {this.state.rows.map(row => ( <div>{row.first} {row.last}</div>) )}
               {/* Again, when state changes, things happen! */}
           </div>
       )
   }
}