Reputation: 37
In my function getFact()
, I make a GET and return the data. The issue that I'm having is that the request is looping infinitely instead of just once.
here's my code:
import React, {useState} from "react";
import axios from "axios";
function Facts() {
const [fact, setFact] = useState("");
const [source, setSource] = useState("");
const [id, setID] = useState("");
function getFact() {
axios.get("https://exampleAPI.com/", { crossdomain: true }).then(response => {
setFact(response.data[0].fact);
setSource(response.data[0].sources);
setID(response.data[0].id);
});
}
getFact();
return (
<div>
<h1 class="text-light fw-light landing-text">{id}</h1>
<p class="text-light">fact number</p>
<hr class="text-light" />
<h1 class="text-light fw-light landing-text">"{fact}"</h1>
<a class="text-light text-decoration-none" href={source} target="_blank" rel="noopener noreferrer">source</a>
<br />
<br />
<button class="btn btn-lg btn-outline-light" onClick={getFact}>
Next Fact
</button>
</div>
)
}
export default Facts;
Any help is appreciated!
Upvotes: 0
Views: 51
Reputation: 110
You have to use the useEffect
hook to handle the API call. The reason why is calls infinitely is because you call getFact
every time the component is rendered, and within getFact
you making a state update. Every time the state is updated the component is re-rendered, which then call getFact
again, causing the infinite loop.
Try something like this:
import React, {useState, useEffect} from "react";
import axios from "axios";
function Facts() {
const [fact, setFact] = useState("");
const [source, setSource] = useState("");
const [id, setID] = useState("");
function getFact() {
axios.get("https://exampleAPI.com/", { crossdomain: true }).then(response => {
setFact(response.data[0].fact);
setSource(response.data[0].sources);
setID(response.data[0].id);
});
};
useEffect(()=>{
getFact();
},[]);
return (
<div>
<h1 class="text-light fw-light landing-text">{id}</h1>
<p class="text-light">fact number</p>
<hr class="text-light" />
<h1 class="text-light fw-light landing-text">"{fact}"</h1>
<a class="text-light text-decoration-none" href={source} target="_blank" rel="noopener noreferrer">source</a>
<br />
<br />
<button class="btn btn-lg btn-outline-light" onClick={getFact}>
Next Fact
</button>
</div>
)
}
export default Facts;
Notice how I called getFact
within useEffect
. It'll call getFact
only when the component is first rendered. useEffect
also accepts a list of dependencies, which will determine if what ever is specified within the function will run. But I passed an empty array as my dependencies. See here, for more information.
Upvotes: 1
Reputation: 2019
From what it appears, you want to run getFact
when the component mounts i.e. once for a component's lifecycle.
To accomplish it, use useEffect
hook with empty dependency array.
import React, {useState, useEffect} from "react";
import axios from "axios";
function Facts() {
const [fact, setFact] = useState("");
const [source, setSource] = useState("");
const [id, setID] = useState("");
function getFact() {
axios.get("https://exampleAPI.com/", { crossdomain: true }).then(response => {
setFact(response.data[0].fact);
setSource(response.data[0].sources);
setID(response.data[0].id);
});
}
// call getFact in a useEffect hook
useEffect(() => {
getFact();
}, []);
return (
<div>
<h1 class="text-light fw-light landing-text">{id}</h1>
<p class="text-light">fact number</p>
<hr class="text-light" />
<h1 class="text-light fw-light landing-text">"{fact}"</h1>
<a class="text-light text-decoration-none" href={source} target="_blank" rel="noopener noreferrer">source</a>
<br />
<br />
<button class="btn btn-lg btn-outline-light" onClick={getFact}>
Next Fact
</button>
</div>
)
}
export default Facts;
In your code, you're calling getFact
function directly in the body of Facts
functional component which means getFact will be called on every render. Also, you're updating the state (setFact
) in the getFact function and hence making the component re-render whenever getFact is called. This creates an infinite loop.
In the above solution, getFact function will only be called when component is mounted.
You can benefit from these resources:
Upvotes: 2