Shashank Shah
Shashank Shah

Reputation: 2167

React - loader doesn't work

I'm using react and I'm trying to display loader when dom is rendering. But I'm really not sure why this ternary operation isn't working. What am I doing wrong here?

import React, { Component } from 'react';
import logo from './logo.svg';
class App extends React.Component 
{
        constructor()
        {
                super(); 
                this.state = {isLoading: true} 
                console.log(this.state.isLoading);
        }
        componentDidMount() 
        { 
                this.setState ({isLoading: false})
                console.log("componentDidMount");
        }
        render()
        {
                return(
                this.state.isLoading ? 
                <div><img src={logo} className="App-logo" alt="logo" /></div>
                : 
                <div> yourPage </div>
                )
        }
}
export default App;

It shows yourPage every time does not show logo image (loader image)

Upvotes: 0

Views: 2534

Answers (3)

Unsal
Unsal

Reputation: 141

Here it is...

Create a isLoading state in constructor with default TRUE value

constructor(props) {
   this.state = { 
       x: ...
       y: ...
       isLoading: true
     }
 }

Update any other state in ComponentDidMount

ComponentDidMount() {
  ...
  this.setState { x: ... }
}

Set isLoading = False in ComponentDidUpdate when state is changed

ComponentDidUpdate(prevProps, prevState) {
    ...
    if (prevState.x !== this.state.x) {
        this.setState = { isLoading: false }   
    }
}

Render your Loader

...
<Loader active={this.state.isLoading} />

Upvotes: 2

Rizal Sidik
Rizal Sidik

Reputation: 989

you can try this one, this is will set your state after several second:

import React, { Component } from 'react';
import logo from './logo.svg';
class App extends React.Component 
{
        constructor()
        {
                super(); 
                this.state = {isLoading: true} 
                console.log(this.state.isLoading);
        }
        componentDidMount() 
        { 
                setTimeout(() => this.setState({isLoading: false}), 3000)
            console.log("componentDidMount");
        }
        render()
        {
                if(this.state.isLoading){
                  return(
                    <div><img src={logo} className="App-logo" alt="logo" /></div>
                  )
                }
                return(
                  <div> yourPage </div>
                )
        }
}
export default App;

this is the simple one if you just to see your loader (using timer), if you want to implement that after getting the API, you can call your API first in componentDidMount or componentWillMount after you have response from API you can set your state to false.

in that code i implement the interval is same with your time to get response from your API. if you want to get data from API, this is the example code :

import React, { Component } from 'react';
import logo from './logo.svg';
class App extends React.Component 
{
        constructor()
        {
                super(); 
                this.state = {isLoading: true} 
                console.log(this.state.isLoading);
        }
        componentWillMount() { 
         fetchAPI()
           .then((response) => {
             this.setState({isLoading: false})
         })
         .catch((error) => {
             console.log('error = ', error)
          }
        }
        render()
        {
                if(this.state.isLoading){
                  return(
                    <div><img src={logo} className="App-logo" alt="logo" /></div>
                  )
                }
                return(
                  <div> yourPage </div>
                )
        }
}
export default App;

Hope it can help you, Thanks :)

Upvotes: 1

GProst
GProst

Reputation: 10227

You set isLoading state to false right after component did mount. It immediately re-renders and shows yourPage respectively (re-render takes just milliseconds).

If you want to set loader before your React app has been loaded, you need to set it directly in your index html file. For example, you have:

<body>
  <div id='root'> // In here you insert your React App component
    // Insert your loader down here
    // It will immediately disappear after React App is inserted
    // (You should use vanilla HTML + CSS - not ReactJS of course)
    // Example:
    <style>
      .my-app-loader {
        // css styles
      }
    </style>
    <div class='my-app-loader'></div>
  </div>
</body>

EDIT

If you want to show loader while waiting for server API response, then you should change isLoading state according to request status. For example:

class App extends React.Component {
  ...
  componentWillMount() { 
    fetchSomeDataFromServer()
      .then((response) => {
        this.setState({isLoading: false})
        // Do what you need with that response data
      })
      .catch((error) => {
        // Handle error
      }
  }
  ...
}
export default App

Upvotes: 1

Related Questions