Patrick José
Patrick José

Reputation: 425

How to map 3 different objects on a table

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

Answers (1)

Gabriel Ferrarini
Gabriel Ferrarini

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

Related Questions