Reputation: 360
I'm trying to fetch some data from the backend and display those data in a dropdown menu.
const[allGroups, setAllGroups] = useState([])
useEffect(() => {
console.log("useEffect")
// get all Groups
fetch("http://localhost:8080/group/getAll")
.then(response => response.json())
.then(data => {
let arr = []
for (let i = 0; i < data.length; i++){
arr.push(data[i]["groupName"])
}
setAllGroups(arr)
})
}, [allGroups])
And this is where I generate things
<Dropdown.Menu>
<Dropdown.Item href="#/action-1">Action</Dropdown.Item>
{
allGroups.map((group, i) => {
return (
<Dropdown.Item key={i}>{group}</Dropdown.Item>
)
})
}
</Dropdown.Menu>
I noticed the useEffect
hook was running basically all the time (even if the value of allGroups
didn't change). I thought useEffect
only runs when the specified elements on the page rerender. Is there a way to only trigger useEffect
when allGroups
change? Thanks!
Upvotes: 1
Views: 1418
Reputation: 457
by using allGroups inside the useEffect
the useEffect
will be re-render the component as long the allGroups
change.
you just need to fetch the APIS
in the first render for the component that will lead you to just use useEffect with empty dependency like this []
. after getting the response
just update the state by using setAllGroups
. then implement what you need on allGroups
const[allGroups, setAllGroups] = useState([])
useEffect(() => {
console.log("useEffect")
// get all Groups
fetch("http://localhost:8080/group/getAll")
.then(response => response.json())
.then(data => {
setAllGroups(data) <= just update the state with the response here.
})
}, []) <= you don't need to add **allGroups** here
Upvotes: 0
Reputation: 112825
Is there a way to only trigger
useEffect
whenallGroups
change?
That's exactly what your code is doing already. However, allGroups
is changing each time the function is run (since you're calling setAllGroups
as part of that function).
If you only want the items to be fetched once (after component's first render), remove allGroups
from the deps array.
If you want to re-fetch the data in response to some user action, define a separate method that can be explicitly called, and then call it appropriately (e.g. when a button is clicked) in addition to calling it within useEffect
with an empty deps array.
Upvotes: 2
Reputation: 16
Just remove allGroups params from useEffect dependencys
this happened because on each render you fetch your data and when fetch success you set new data to all Groups state that make useEffect rerender
const[allGroups, setAllGroups] = useState([])
useEffect(() => {
getAllGroups()
}, [])
const getAllGroups = () => {
fetch("http://localhost:8080/group/getAll")
.then(response => response.json())
.then(data => {
let arr = []
for (let i = 0; i < data.length; i++){
arr.push(data[i]["groupName"])
}
setAllGroups(arr)
})
}
Upvotes: 0