I have a list with items that first loads 30 items and if the user clicks on "Load All", rest of the items are shown:
+---------------------------------------------------------+
| |
| List |
| |
| |
| |
+---------------------------------------------------------+
| Load All Button |
+---------------------------------------------------------+
When the list is big (more than 1K items) the rendering of the "Load All" step takes some time and meanwhile the DOM is stuck and not responsive.
What is the right way to tap into React's lifecycle events so that upon clicking the button it will change to a loading spinner and when the list is fully rendered and ready it will change back ?
I have tried separating the two parts (list and button) to two components and wrap them in a parent component that holds a "loading" and then changing the state in the List componentDidUpdate
function, but it didn't work
http://jsfiddle.net/wh4z60m6/4/
A workaround is to add the spinner class to the react container, and use the :empty pseudo class. The spinner will be visible, as long as nothing is rendered into the container (comments don't count). As soon as react renders something other than comment, the loader will disappear.
Use the react-promise-tracker usePromiseTracker hook. render( <div> <App /> + <LoadingIndicator/> </div>, document.
js with the following code: import React from 'react'; import spinner from './spinner. gif'; function Spinner() { return ( <div> <img src={spinner} style={{ width: '100px', margin: 'auto', display: 'block' }} alt="Loading..." /> </div> ); }; export default Spinner; Here, we import the .
You can hide spinner in the ProgressButton by setting the e-hide-spinner property to cssClass .
Rendering in React is synchronous, which means nothing else can run alongside it.
You could render your list progressively since the user's screen probably can't display more than a hundred items at a time.
Also, note that rendering thousands of items is much slower in the development build than in the production build of React.
EDIT: Another option would be to first render the loader, then render your list items on the next frame. The loader 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>
);
},
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With