The spinner is showing when I put it on a component did mount method with a setTimeOut method inside. However, I want the Soinner to show when there is no content on the page, only after thge axios request is done loading does it show the page content isntead of the loading indicator. I have put the this.state.loaded as a default of false. When user clicks submit, the axios request is processing and triggers a setState of loaded to true.
I have tried conditional rendering such as
{this.state.loaded && <LoadingIndicator/>}
and
this.setState({ loaded: false }, () => {
axios.get(`https://www.food2fork.com/api/searchkey=${API_KEY3}&q=${this.state.name}`)
.then(result => this.setState({
loaded: true,
ingredients:res.data.recipes,
}));
});
//Recipes.js
import React from "react";
import axios from "axios";
import LoadingIndicator from "./loadingIndicator"
const API_KEY="f562842f0ff6b2d4fd24b9601aeb5e1b";
const API_KEY2="bfb76b78b11e7308cc3c027865a508dd";
const API_KEY3="726237903540780fabd8614c1fe4e75d"
class Recipes extends React.Component {
state= {
ingredients:[this.props.ingredients],
loaded:false
}
handleChange=(e)=> {
this.setState({
[e.target.id]: e.target.value
})
}
handleSubmit=(e)=> {
e.preventDefault();
console.log(this.state);
axios.get(`https://www.food2fork.com/api/search?key=${API_KEY3}&q=${this.state.name}`)
.then(res=> {
console.log(res)
this.setState({
ingredients:res.data.recipes,
})
})
}
render() {
const recipeList = this.state.ingredients.length >0? this.state.ingredients.map((ingredient)=> {
return(
<div key={ingredient.recipe_id}>
<img className="recipeImage" src={ingredient.image_url}/>
<p>{ingredient.title}</p>
</div>
)
}) : <LoadingIndicator loaded={this.state.loaded}/>
return(
<div style={{padding:50}}>
<form className="form" onSubmit={this.handleSubmit}>
<label>Food Name or Ingredient: </label>
<input
id="name"
onChange={this.handleChange}
className="formText"
type="text"
placeholder="type in ingredient or recipe"
/>
<button className="btn waves-effect waves-light" type="submit" name="action">Submit</button>
</form>
<div style={{marginTop:100}}>
{recipeList}
</div>
</div>
);
}
}
export default Recipes;
//LoadingIndicator.js
import React from 'react';
import { css } from '@emotion/core';
// First way to import
import { ClipLoader } from 'react-spinners';
// Another way to import. This is recommended to reduce bundle size
const override = css`
display: block;
margin: 0 auto;
border-color: red;
`;
class LoadingIndicator extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<div className='sweet-loading' style={{marginTop:150}}>
<ClipLoader
css={override}
sizeUnit={"px"}
size={350}
color={'#123abc'}
loading={this.props.loading}
/>
<h1>LOADING...</h1>
</div>
)
}
}
export default LoadingIndicator;
Your Logic for spinner is little off, But try this one. Spinner is shown only in axios request.
class Recipes extends React.Component {
state= {
ingredients:[this.props.ingredients],
loading:false
}
handleChange=(e)=> {
this.setState({
[e.target.id]: e.target.value
})
}
handleSubmit= (e)=> {
this.setState({loading:true}) //starts spinner
e.preventDefault();
axios.get(`https://www.food2fork.com/api/search?key=${API_KEY3}&q=${this.state.name}`)
.then(res=> {
this.setState({
ingredients:res.data.recipes,
}) // ***write catch function to catch error
}).finally(function(){
loading:false // stop spinner (in response/error)
})
}
render() {
const recipeList = this.state.loading ? // if loading is true, show loader
<LoadingIndicator loaded={this.state.loaded}/>
:
this.state.ingredients.length <= 0 ? // check if ingredients have length equals to zero, then show
'No ingredients available'
:
this.state.ingredients.map((ingredient)=> { // else loop and show each ingredients
return(
<div key={ingredient.recipe_id}>
<img className="recipeImage" src={ingredient.image_url}/>
<p>{ingredient.title}</p>
</div>
)
});
return(
<div style={{padding:50}}>
<form className="form" onSubmit={this.handleSubmit}>
<label>Food Name or Ingredient: </label>
<input
id="name"
onChange={this.handleChange}
className="formText"
type="text"
placeholder="type in ingredient or recipe"
/>
<button className="btn waves-effect waves-light" type="submit" name="action">Submit</button>
</form>
<div style={{marginTop:100}}>
{recipeList}
</div>
</div>
);
}
}