Show a loading animation while your elements are loading in React

in #utopian-io7 years ago (edited)


Source

What Will I Learn?

As you might have seen, some modern web sites and web application show a loading animation, also known as a throbber, when there is content being loaded. This kind of animations tell the user that there is content that is being fetched and that it is not available yet. Once the content is fully fetched, the throbber disappears. In this tutorial you will learn how to display a throbber while you are making an async request, or there is content that is not ready to be displayed.

  • How to render content conditionally in a React web application according to the component's state
  • How to use throbbers

Requirements

You will need the following requirements in order to complete this tutorial. In the curriculum section there are some links that you can check if you don't know much about React and how to create an application in React.

  • Node.js
  • NPM
  • create-react-app

Difficulty

  • Intermediate

Tutorial Contents

Creating our application

First, we need an application. Here, we are going to create a new one:

$> create-react-app throbber-demo
$> cd throbber-demo
$> npm start

image.png

Installing react-loader

Now, we should have our React application running in our browser. In another terminal tab or window we are going to install react-loader module using NPM. This module will allow us to use a throbber easily.

$> npm install --save react-loader

image.png


Ignore the warnings

Setting up our components

Now we are ready to start coding. First, we are going to be editing the file called App.js inside the path ~/throbber-demo/src/App.js. Here is what my project looks like:

image.png

And this is what is left after cleaning up the App.js file for what we need:

image.png

Setting up the logic of the component

What we are trying to do with this tutorial is: display a throbber in the web application while there's content being loaded, and then hide it when the content is ready. We are going to use React's state to achieve this because every time we modify the state in a React component, it's re-rendered (reloaded). So, our initial state will be that the content is not ready, then we will fetch the content, and once we finish fetching the content, show it and hide the throbber.

Setting up the initial state

We need to set the default values for our state in the constructor of the component. The constructor is a piece of code that will initialize and declare some initial values for an instance of a class, so, every time we make a new instance of a certain class, we will have enough information to use it properly. In this case, we need an initial state:

constructor(props){
    super(props);
    this.state = {ready: false};
  }

So far, do not worry about what the super and props part means. We do not need them right now.

Showing the throbber when the component is mounted

Now, we need to tell our component what to do with the information we have. That means, showing the throbber while the ready value inside the state isn't true. In order to do this, we are going to need to modify the render() method of our component:

render() {
    if(this.state.ready) {
      return(
        <span>Fetched content</span>
      );
    }
    else{
      return(
        <span>Throbber</span>
      );
    }
  }

This basically means that while the value of ready inside the state isn't true, the throbber will be showed. Actually, if we go to our browser, we will see the message we just configured. But an <span> is not a throbber.

image.png

Now, we need to import the Loader module we installed before, and we do it in the top part of our component:

import React, { Component } from 'react';
import Loader from 'react-loader';

And now, we will replace the <span> with the throbber:

render() {
    if(this.state.ready) {
      return(
        <span>Fetched content</span>
      );
    }
    else{
      return(
        <Loader/>
      );
    }
  }

And now, we have a throbber:

image.png

Changing the component's state

If we don't do anything else, we are going to see a throbber all the time, we need to change this. We are going to fetch some information from an API. I'm going to use the CoinMarketCap API to fetch some data about the Bitcoin price.

Right now, I want my component to start loading the information right when I open the application, so I don't need to click any button. We can achieve this behavior using the componentWillMount() method. This method belongs to a set of method that conforms the React lifecycle's methods, that we can use to trigger some actions in different points during the life of the components. Right now, we need to get something done just by the time our component is mounted, so this method is perfect. In order to use it, we just put it below the constructor code:

  constructor(props){
    super(props);
    this.state = {ready: false};
  }

  componentWillMount() {
    // code goes here
  }
Fetching the information

We are going to use the fetch() method to make the request to the API. This code goes inside the definition of componentWillMount():

componentWillMount() {
    fetch('https://api.coinmarketcap.com/v1/ticker/bitcoin/')
    .then(res => res.json())
    .then(response => this.setState({data: response, ready: true}))
    .catch(err => {
      alert('An error ocurred');
      console.log(err);
    });
  }

As you can see, I created a new element inside my state called data that will hold the data that was fetched, and then I changed the value of ready to true. Now, if we check our browser, we we'll see the other message we configured to appear when the throbber is not being displayed:

image.png

Let's display the information we just fetched:

render() {
    if(this.state.ready) {
      var change_color = this.state.data[0].percent_change_24h > 0 ? 'green' : 'red';
      return(
        <div>
          <h1>{this.state.data[0].name} ({this.state.data[0].symbol})</h1>
          <h2>Price: {this.state.data[0].price_usd}$</h2>
          <div style={{display: 'inline'}}>
            <h2 style={{display: 'inline-block'}}>Change 24h: </h2>
            <h2 style={{color: change_color, display: 'inline-block'}}> {this.state.data[0].percent_change_24h}%</h2>
          </div>
        </div>
      );
    }
    else{
      return(
        <Loader/>
      );
    }
  }

And it will look like this:

image.png

Refreshing the content

Let's create a button that will allow us to refresh the price of the currency I selected. In order to do this, we need to create a button, and associate and action when it's clicked:

<button onClick={this.refreshPrice}>Refresh price</button>

Now, let's declare this refreshPrice method inside the constructor of our component, so we can define and use it.

constructor(props){
    super(props);
    this.state = {ready: false};
    this.refreshPrice = this.refreshPrice.bind(this);
  }

This basically tells our component that there is something called refreshPrice that is inside it. After we've declared our new method in the constructor, we define it below the componentWillMount method:

refreshPrice(e) {
    e.preventDefault();
    this.setState({ready: false}, () => {
      fetch('https://api.coinmarketcap.com/v1/ticker/bitcoin/')
      .then(res => res.json())
      .then(response => this.setState({data: response, ready: true}))
      .catch(err => {
        alert('An error ocurred');
        console.log(err);
      });
    });
  }

What this method does is, activate the throbber by setting the ready value to false, fetch the info, and once it gets the new information, set the ready value to true again, so the throbber is shown while we are getting the data.

image.png

Here is a demonstration of what it looks like when working.

Here is a Github gist with all the code I used in my App.js file.

If you have any comments, questions or suggestions leave them in the comments section
All the screenshots were taken by me

Curriculum



Posted on Utopian.io - Rewarding Open Source Contributors

Sort:  

Thank you for the contribution. It has been approved.

  • We prefer tutorials as a whole as possible instead of dozens of parts. So, next time, please merge some topics together.

You can contact us on Discord.

[utopian-moderator]

Hello @yokunjon, thank you for reviewing my post. But I don't understand very well your suggestion. Even though I have been writing React tutorials, I have been writing about very different topics and using different libraries each time in order to accomplish different goals. I've been trying to cover up as much as possible in every tutorial so everything is well explained. What am I doing wrong? Can you give an example? Regards!

Instead of showing different libraries, you can generalize them by "how to use graphics libraries" and give some example. So by that way, the user can generalize what you taught them and can use all similar libraries. Of course, some aspects are not possible to merge with another. But if possible, do not be shy.

Oh, ok. I got it. Thank you!

Hey @jfuenmayor96 I am @utopian-io. I have just upvoted you!

Achievements

  • You have less than 500 followers. Just gave you a gift to help you succeed!
  • Seems like you contribute quite often. AMAZING!

Suggestions

  • Contribute more often to get higher and higher rewards. I wish to see you often!
  • Work on your followers to increase the votes/rewards. I follow what humans do and my vote is mainly based on that. Good luck!

Get Noticed!

  • Did you know project owners can manually vote with their own voting power or by voting power delegated to their projects? Ask the project owner to review your contributions!

Community-Driven Witness!

I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!

mooncryption-utopian-witness-gif

Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x

Felicidades te admiro mucho hijo Dios te de mucho mucho más conocimiento, me recuerdas alguien que ya no está a mi lado pero se que hoy en día está mejor,saludos y mucho éxito.

Congratulations @jfuenmayor96! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 2 years!

You can view your badges on your Steem Board and compare to others on the Steem Ranking

Vote for @Steemitboard as a witness to get one more award and increased upvotes!