Reputation: 37
I need the background to change colors at the same time the api request is rendered.
I am building a Quote generator. Its a simple one button interface, that once clicked, loads a new quote and changes the background color. I could not find a good way to bind two methods to the same click event, so I have the API call and the color change taking place in the same method. The problem is, the color changes instantly, but the quote takes time to update. I tried calling component DidMount inside the method, but this did not work. I am sure there is an easier approach, I am just missing it. Here is my code
import React, { Component } from 'react'
import Button from './Button';
import axios from 'axios'
class QuoteBox extends Component{
constructor(props){
super(props)
this.state = {
quotes: [],
colors: ["#16a085", "#27ae60",
"#2c3e50", "#f39c12",
"#e74c3c", "#9b59b6",
"#FB6964", "#342224",
"#472E32", "#BDBB99",
"#77B1A9", "#73A857"]
}
}
componentDidMount(){
axios.get('http://quotesondesign.com/wp-json/posts?
filter[orderby]=rand&filter[posts_per_page]3')
.then(res=> this.setState({quotes: res.data[0]}))
}
getNext = (ev) =>{
const {colors} = this.state
const color = colors[Math.floor(Math.random()* colors.length)]
var newQuote = Math.floor(Math.random() * 50)
const API_URL = `http://quotesondesign.com/wp-json/posts?
filter[orderby]=rand&filter[posts_per_page]${newQuote}`
ev.preventDefault()
document.body.style.backgroundColor = color
axios.get(API_URL)
.then(res=> this.setState({quotes: res.data[0]}))
document.body.style.backgroundColor = color
}
render(){
const {content,title} = this.state.quotes
const filteredContent = String(content).replace(/(<\w>)|(<\/\w>)|
(&#\d{4})|(<\w* \/>)|(\/\w*)/gm, "").replace(/(;)/g,"'")
console.log(content)
return(
<React.Fragment>
<h2>A little inspiration for the day</h2>
<div className='outerQuoteBox'>
<div className='innerQuoteBox'>
<p>{filteredContent}</p><br/><br/>{title}
</div>
<Button getNext={this.getNext} />
</div>
</React.Fragment>)
}
}
export default QuoteBox
And this is my button component
import React, { Component } from 'react'
export class Button extends Component {
render() {
return (
<button onClick={this.props.getNext} className='nextBtn'
type='button'>Next<button/>
)
}
}
export default Button
I am going to have the font color change with the background as well,and I think I can figure that out, but the color changing so much sooner than the quote changing makes the whole thing look bad. It needs to happen all at once.
Upvotes: 0
Views: 87
Reputation: 1680
You have two options with your current setup: you can change the background in a callback for your setState
call, or, you can call it in the same function you're passing to your then
clause from Axios.
Why? Axios returns a Promise which represents the eventual completion of an asynchronous request (i.e, API call). Your .then()
call is fired upon a successful (non-error-throwing) completion of the request.
Your code otherwise keeps executing, hence, why your background was changing before your API call completed.
then()
getNext = (ev) =>{
const {colors} = this.state
const color = colors[Math.floor(Math.random()* colors.length)]
var newQuote = Math.floor(Math.random() * 50)
const API_URL = `http://quotesondesign.com/wp-json/posts?
filter[orderby]=rand&filter[posts_per_page]${newQuote}`
ev.preventDefault()
document.body.style.backgroundColor = color
axios.get(API_URL)
.then(res=> {
this.setState({quotes: res.data[0]});
document.body.style.backgroundColor = color;
});
}
setState callback
getNext = (ev) =>{
const {colors} = this.state
const color = colors[Math.floor(Math.random()* colors.length)]
var newQuote = Math.floor(Math.random() * 50)
const API_URL = `http://quotesondesign.com/wp-json/posts?
filter[orderby]=rand&filter[posts_per_page]${newQuote}`
ev.preventDefault()
document.body.style.backgroundColor = color
axios.get(API_URL)
.then(res=> {
this.setState({quotes: res.data[0]}, () => {
document.body.style.backgroundColor = color;
});
});
}
Upvotes: 1