reactjsloaderreact-loadablesvg-react-loader

React Loader - Trying to get a loader when api request is made and to stop it when response is fetched


What I want is that, when I click on search button, then a loader/spinner should appear on screen until the data is fetched, when the data is fetched it should disappear.

Container.jsx

import React from 'react';
import './container.css'
import Weather from './weather';
var Loader = require('react-loader');
class Container extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            location: "",
            weather: [],
            loaded:false
        };
    }
    handleChange = (e) => {
        this.setState({ [e.target.name]: e.target.value });
    };

    componentDidMount() {
        this.setState.loaded=false;
    }

    continue = (e) => {
        this.setState({loaded:true});
        const { location } = this.state;
        const rawurl = 'http://api.weatherstack.com/current?access_key=d8fefab56305f5a343b0eab4f837fec1&query=' + location;
        const url = rawurl;
        e.preventDefault();
        if (location.length < 1) {
            return alert('Enter the details');
        }
        else {
                fetch(url)
                    .then(response => response.json())
                    .then(data =>{
                        this.setState({weather:[data],loaded:false});
                    })
                    .catch(err => console.log("error ",err)) 
        }
    };
    render() {
        console.log(this.state.weather);
        const weather =
        this.state.weather.length> 0 ? 
        this.state.weather.map(item => (<Weather location={item.location.name} temperature={item.current.temperature} weather={item.current.weather_descriptions[0]} windSpeed={item.current.wind_speed} windDegree={item.current.wind_degree} windDir={item.current.wind_dir} humidity={item.current.humidity} visibility={item.current.visibility} />
            ))
        :<span></span>
        return (
            <div id="container">
                <div class="searchicon">
                    <input type="search" placeholder="Enter City !!" type="text" name="location" value={this.state.location} onChange={this.handleChange}></input>
                    <label class="icon">
                        <button onClick={this.continue} id="btn"><span class="fa fa-search"></span></button>
                    </label>
                </div>
                <div>
                    <Loader loaded={this.state.loaded}>
                      {weather}
                    </Loader>
                </div>
                
            </div>
        );
    }
}
export default Container;
What I am using here is react-loader But right now,its not happening in the way I want, sometime before clicking the serach button it appears and when data is fetched it stops, i want to start it when the api req is made after click on search button and to stop when data is fetched.


Solution

  • first of all you should in the setState after fetching the data to make

    this.setState({weather:[data],loaded:true});
    

    second there's another way to do it you can separate the code in the return function like

    { !this.state.loaded ? <Loader loaded={false} options={options} className="spinner" />:{weather}}
    

    as per the Doc in npm you can check it react-loader