Reputation: 33
I was playing around with React a bit and I'm facing a spicy issue which I can't figure out.
I have a Joke Component which is basically supposed to make a request to https://sv443.net/jokeapi/v2
and display the results. Making the request and updating my state is all done in a method, which is then called in the componentDidMount() method.
This works perfectly fine, but I wanted to make the component make more requests to the API on click, so what I tried doing was setting the Component's onClick value equal to the method that makes the XMLHttpRequest.
My issue is that doing this makes my page spam the api with requests, so there are various jokes being requested per one click, whereas I just want one joke per click.
The code's right below:
class Joke extends React.Component {
constructor(props) {
super(props);
this.state = {
joke: '',
hover: false
};
this.getJoke = this.getJoke.bind(this);
}
//GET request for the joke
getJoke = () => {
let that = this;
// this.setState({ joke: '' });
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200) {
console.log(this.response);
that.setState({ joke: this.response })
}
}
xhr.open('GET', 'https://sv443.net/jokeapi/v2/joke/Programming,Miscellaneous?blacklistFlags=nsfw,racist,sexist&format=txt');
xhr.send();
}
componentDidMount() {
this.getJoke();
}
render() {
let jokeClass = 'text' + (this.state.hover ? '' : ' shy');
console.log(jokeClass);
console.log(this.state.joke);
return (
<div id='joke' className={jokeClass} onMouseEnter={() => this.setState({ hover: true })} onMouseLeave={() => this.setState({ hover: false })} onClick={this.getJoke()}>
<p id='qualityContent'>
{!this.state.hover && 'Hover over me for a joke.\nClick me for another one.'}
{this.state.joke.length > 0 && this.state.hover && this.state.joke}
{this.state.joke.length === 0 && this.state.hover && 'Joke incoming'}
</p>
</div>
);
}
}
I'd greatly appreciate any insight you guys can give me :)
Upvotes: 3
Views: 802
Reputation: 481
Use onClick={() => this.getJoke()}
or onClick={this.getJoke}
. Currently you are running this function when render is called and a result of it would be assigned to onClick.
Edit:
One of the mentioned version should be used instead of onClick={this.getJoke()}
on <div>
element.
The reason is that by setting onClick={this.getJoke()}
you tell React on render to call your getJoke
method and assign a result of it as a onClick
handler for runtime. Now, because getJoke()
is making a request and setting a state value, here's what happens:
this.getJoke()
that.setState({ joke: this.response })
onClick={this.getJoke()}
so your method would be called.Upvotes: 4