Reputation: 425
I am trying to map 3 different objects that I get when I make a call to an API.
The goal is to print async, one at a time so the page does not take many time to load.
There's just one call that gets these objects, it's a call to a dynamic URL, so I change the parameters on a loop and I get the response.
The objects come like this:
Object 1
{
Name: one
Group: one
}
Object 2
{
Name: two
Group: two
}
Object 3
{
Name: three
Group: three
}
What I was trying to achieve was mapping these objects one per line, like a table:
Name: one Group: one
Name: two Group: two
Name: three Group: three
Instead, I get them on the same line. The object changes from the first one to the last. The last stays, as if iterating through all of them and stopping at the last one.
My call to the API:
export default function Machines({data}) {
const classes = useStyles()
const style = styles();
const name_Machines = data.map((row)=>{
return (row.name);
});
const resource_group = data.map((row)=>{
return (row.resource_group);
});
let url
const [MachinesRow, setMachinesRow] = React.useState([])
React.useEffect(() => {
resource_group.forEach((keyword, index) => {
url = "/api/machine/" + keyword + "/" + name_Machines[index]
fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + window.localStorage.getItem("access_token"),
},
})
.then(resp => {
return resp.json()
})
.then(data => {
setMachinesRow([...MachinesRow, ...[data]])
})
.catch(error => {
console.log(error)
window.localStorage.removeItem("access_token")
window.location.replace("/")
})
})
}, [])
My code:
return (
<div className={classes.root}>
<h1>Azure machines</h1>
<Table className={classes.table} size="small">
<TableHead>
<TableRow>
<TableCell align="left">name</TableCell>
<TableCell align="left">resource_group</TableCell>
<TableCell align="left">location</TableCell>
<TableCell align="left">status</TableCell>
</TableRow>
</TableHead>
<TableBody>
{MachinesRow.map(row => (
<TableRow key={row.name + row.resource_group}>
<TableCell align="left" component="th" scope="row">
<StyledButton size = "small" className={style.size3}>
<Link style={{ color: 'inherit', textDecoration: 'inherit'}} to={`/machines/${row.resource_group + "/" + row.name}`}>{row.name}</Link>
</StyledButton>
</TableCell>
<TableCell align="left">{row.resource_group}</TableCell>
<TableCell align="left">{row.location}</TableCell>
<TableCell key= {row.name + row.resource_group}align="left">
<MachineStatusIcon
status_code={row.status_code}
status={row.status}
/>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
)
}
Upvotes: 0
Views: 97
Reputation: 961
When you set your callback functions to call:
setMachinesRow([...MachinesRow, ...[data]])
you are creating a new Array object while using the original MachinesRow which is an empty Array object (You create all 3 callbacks from the same scope). Doing it 3 times will leave you with the last data set, because each one will replace the previous with empty data + the request result.
Edit
Do this instead.
React.useEffect(() => {
const resultsPromise = resource_group.map((keyword, index) => {
url = "/api/machine/" + keyword + "/" + name_Machines[index]
return fetch(url, {...})
.then(resp => resp.json())
.catch(error => {
console.log(error)
window.localStorage.removeItem("access_token")
window.location.replace("/")
})
})
Promise.all(resultsPromise).then(results => setMachinesRow([...MachinesRow, ...results]));
}, [])
You might need to work the data on results, this is just an example of how to set you in a position where you have all your data in one place
Upvotes: 1