1

I have a table in which data is called from an API. However the table and the header loads first and I have to wait for the API data to load into the body. I want to implement a loading screen spinner until the data has been fetched and the page then renders Here is my code..

Content.js

import React from 'react';
import axios from 'axios';

class Content extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: [],

        }
    }

    componentDidMount() {

        axios.get('https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=true')
            .then(res => {
                const data = res.data;
                this.setState({  data: data})
            })
    }


    render() {
        return (

        <div>
            <table border="1">
                <thead>
                    <tr>
                    <td>Name</td>
                    <td>Price</td>
                    </tr>
                </thead>
                <tbody>
                    {this.state.data.map((n) => {
                    return (
                        <tr>
                        <td >{n.name}</td>
                        <td> {n.current_price} </td>
                        </tr>
                    );
                    })}
                </tbody>
            </table>
        </div>

        );
    }
}

export default Content;

In my index.html file I have the code for the spinner

Index.html

<!-- head -->

 <style>
      .svgLoader {
        animation: spin 0.5s linear infinite;
        margin: auto;
      }
      .divLoader {
        width: 100vw;
        height: 100vh;
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 9999;
      }
      @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
      }
    </style>

<! -- body -->

 <div  id="root">
      <div class="divLoader">
        <svg class="svgLoader" viewBox="0 0 100 100" width="10em" height="10em">
          <path stroke="none" d="M10 50A40 40 0 0 0 90 50A40 42 0 0 1 10 50" fill="#51CACC" transform="rotate(179.719 50 51)"><animateTransform attributeName="transform" type="rotate" calcMode="linear" values="0 50 51;360 50 51" keyTimes="0;1" dur="1s" begin="0s" repeatCount="indefinite"></animateTransform></path>
        </svg>
 </div>

This spinner works but how do I make it continue working until the API call is completed as the table loads without the data present for another few seconds

1 Answer 1

4

You have added the loading animation into the root container as static HTML which will be filled with the React application. Which is fine, we also do that to make the initial loading screen really fast.

But the problem is that React renders the application and removes your static HTML and replaces it with the application even though your component is still loading its data.

So you will have to re-add the loading HTML using JSX.

I suggest that you create a Loader component and render this while the data is loading, like so:

import React from 'react';
import axios from 'axios';

const Loader = () => (
  <div class="divLoader">
    <svg class="svgLoader" viewBox="0 0 100 100" width="10em" height="10em">
      <path stroke="none" d="M10 50A40 40 0 0 0 90 50A40 42 0 0 1 10 50" fill="#51CACC" transform="rotate(179.719 50 51)"><animateTransform attributeName="transform" type="rotate" calcMode="linear" values="0 50 51;360 50 51" keyTimes="0;1" dur="1s" begin="0s" repeatCount="indefinite"></animateTransform></path>
    </svg>
  </div>
);

class Content extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            loading: true,
            data: [],
        }
    }

    componentDidMount() {

        axios.get('https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=true')
            .then(res => {
                const data = res.data;
                this.setState({ data, loading: false })
            })
    }


    render() {
        return (

        <div>
            {this.state.loading ? <Loader /> : null}
            <table border="1">
                <thead>
                    <tr>
                    <td>Name</td>
                    <td>Price</td>
                    </tr>
                </thead>
                <tbody>
                    {this.state.data.map((n) => {
                    return (
                        <tr>
                        <td >{n.name}</td>
                        <td> {n.current_price} </td>
                        </tr>
                    );
                    })}
                </tbody>
            </table>
          }
        </div>

        );
    }
}

export default Content;
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the help. Much appreciated!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.