React show spinner while DOM is rendering

I have a list with items that first load 30 items, and if the user clicks "Download All", the rest of the items are displayed:

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

When the list is large (more than 1K items), the rendering of the “Download All” phase takes some time, while the DOM is stuck and does not respond.

What is the right way to trigger React's life cycle events so that when you click a button it changes to the bootloader and when the list is fully displayed and ready it will change?

I tried to separate the two parts (list and button) into two components and wrap them in the parent component that contains the “load”, and then changed the state in the “ componentDidUpdate List” function, but this did not work

jsfiddle

http://jsfiddle.net/wh4z60m6/4/

+7
reactjs
source share
2 answers

The rendering in the Reactor is synchronous, which means that nothing else can work with it.

You can make your list gradually, as the user’s screen probably cannot display more than a hundred items at a time.

Also note that rendering thousands of elements is much slower in a development assembly than in a production React assembly.

EDIT: Another option is to first render the loader and then display the list items on the next frame. The bootloader will be displayed until the list items have finished rendering.

 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> ); }, }); 
+8
source share

Here is a simple class with a more recent React 16 example (with comments for clarity):

 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> ) } } 
0
source share

All Articles