I have a list of names inside an array that I need to get data for.
My goal is to use a for-loop that will iteratively perform an API call for each name in the list, with the data from every call being stored into an object inside a Person (useState) array. So far I've put together a component but it seems to cause the entire site to become glitchy and malfunction.
I believe it may be coming from the way I've used the loop inside the useEffect, but I'm not entirely sure. Is there a better approach to implementing the component below?
function API_CALL(){
const [Person, SetInfo] = useState([
{
age:'',
occupation:''
}
])
const names = [
"bob",
"alice",
"jerry",
"steve",
"tracy",
"hank"
]
useEffect(() => {
for(let i = 0; i <= 5; i++){
fetch('https://api.userfacesite.com/api/v3/data/' + names[i], {
headers: {
'Accept': 'application/json',
'Path': '/',
}
})
.then(response => response.json())
.then(json=>
SetInfo([...person, {age:json.person.age, occupation:json.person.occupation}])
);
}
},[Person]);
return(
<div>
{JSON.stringify(Person)}
</div>
)
}
Your implementaion can be better with some changes.
First, you need a function to call your API's which can be implemented with useCallback hook or with a regular function outside of useEffect, also you need a catch block for failure API call:
function fetchData (name) {
fetch('https://api.userfacesite.com/api/v3/data/' + name, {
headers: {
'Accept': 'application/json',
'Path': '/',
}
})
.then(response => response.json())
.then(json=> SetInfo(prevState =>
([...prevState, {age:json.person.age, occupation:json.person.occupation}])))
.catch(error => // do a proper action on error case)
}
Note: for adding previous data, use prevState inside of your setInfo.
You have faced some issues here because every time the person array gets changes and causes triggers the useEffect.
Note: use standard names for creating and setting the state, also use same names:
const [persons, setPersons] = useState()
Now, time to call the fetchData function on your names array:
useEffect(() => {
names.forEach(name => fetchData(name))
}, [])
// with an empty array of dependencies, the hook will only invoke on component did mount once.
Optionally:
You may need to render the persons array (an array of objects) on the page, the example below shows this sample implementation:
return(
<div>
{
persons.map( person => (
<div>Name: {person.name}</div>
<p> age: {person.age} </p>
// and so on for the rest ...
))
}
</div>
)