Lukáš Unzeitig
Lukáš Unzeitig

Reputation: 439

Loading screen during render (asynchronous rendering)

I have one complex component, that is rendering a few seconds. This component contains large canvas with a lot of items. Is there any way how to render some icon during waiting on this Print component?

render(){
  const {data} = this.props;
  return(
    <Page>
      <div className="item column-3" id="graphColumn">
        {this.state.loading ? <img src={loadingIcon}/> : false}
        <div className={this.state.loading ? "hidden" : "visible"}>
          <Print channels={this.state.channels} readyToRender={this.readyRender.bind(this)}/>
        </div>
      </div>
    </Page>
  )
}
readyRender(){
  this.setState({
    loading: false
  })
}

I tried to set display:none during rendering, and after in componentDidMount in Print component set display:auto, but this doesn't work.It take long time too. Any tips for solution?

Upvotes: 2

Views: 1273

Answers (1)

Chris
Chris

Reputation: 59531

There are ways, but probably not in the sense you were hoping for.

React executes its rendering synchronously which means nothing else can be run in parallel. However, if you can control when a time-consuming render will be executed, you can add your waiting icon beforehand.

Here's an example:

var Demo = React.createClass({
  getInitialState: function() {
    return {loading: true};
  },
  componentDidMount: function() {
    setTimeout(() => {
      this.setState({loading: false});
    }, 1000);  //delay this to allow React to actually render the initial state. Can be set to just 10ms, but then font-awesome css doesn't load in time from CDN.
  },
  render: function() {
    if(!this.state.loading) return <div>{this.simulateSlowRender()}</div>;
    return <div><i className="fa fa-spinner fa-spin fa-fw" aria-hidden="true"></i> loading...</div>;
  },
  simulateSlowRender: function() {
    let arr = new Array(10000000);
    arr.push("done!");  //the last item prints "done".
    return <div>{arr.map((item) => item)}</div>;
  }
});

ReactDOM.render(
  <Demo />,
  document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />

<div id="container"></div>

Warning: Note that this will "hang" your entire application until rendering is complete. Javascript animations are unlikely to work during that time.

Upvotes: 2

Related Questions