Array.push() always stacking the last foreach item

Asked

Viewed 516 times

5

I am working on the development of a dynamic table and I am facing problems to create the rows of this table according to the columns I have and the information I receive from the API.

Considering the following code:

let data = [];
let line = {};

const columns = [{
  name: "Code",
  dataIndex: "id"
}, {
  name: "Name",
  dataIndex: "name"
}];

const arrFromApi = [{
  id: 1,
  name: "Marcus",
  age: "32"
}, {
  id: 2,
  name: "John",
  age: "30"
}, {
  id: 3,
  name: "Emily",
  age: "25"
}];

arrFromApi.forEach(item => {
  columns.forEach(column => {
    line[column.dataIndex] = item[column.dataIndex];
  })
  data.push(line)
});

console.log(data)

I have the following result:

[{id: 3, name: "Emily"}, {id: 3, name: "Emily"}, {id: 3, name: "Emily"}]

But if I replace my data.push(line) for console.log(line) is printed on the console correctly each of the names as needed:

[{id: 1, name: "Marcus"}, {id: 2, name: "John"}, {id: 3, name: "Emily"}]

Would anyone know what’s wrong with this scenario? Because I understand that if the console is printing in this sequence, then the end result of my array should be the same.

2 answers

5


What happens is that with each iteration you are overwriting the id and name of the object line.

The correct would be to create a new object at each iteration:

let data = [];

const columns = [{
  name: "Code",
  dataIndex: "id"
}, {
  name: "Name",
  dataIndex: "name"
}];

const arrFromApi = [{
  id: 1,
  name: "Marcus",
  age: "32"
}, {
  id: 2,
  name: "John",
  age: "30"
}, {
  id: 3,
  name: "Emily",
  age: "25"
}];

arrFromApi.forEach(item => {
  let line = {}; // <--- Aqui
  columns.forEach(column => {
    line[column.dataIndex] = item[column.dataIndex];
  })
  data.push(line)
});

console.log(data)

The console.log only "works" because it shows the data you just set in line. But since it is the same object in all iterations, in the end you end up with 3 copies of it in the array data. When creating a new object with each iteration, you eliminate this problem.

1

Another way is to convert the object line in string at each iteration of forEach using JSON.stringify() and parsing with JSON.parse():

data.push(JSON.parse(JSON.stringify(line)));

With this you will not be adding the same object in the array data, but an object with independent value of the object line.

What you’re doing is basically this:

data[line, line, line]

Where the variable line is an object that at the end of the forEach will have as value the last object of the array arrFromApi, that is to say {"id":3,"name":"Emily"}, as said in hkotsubo response.

In this case, you can keep your code as is, just by changing the line of the push as mentioned above:

let data = [];
let line = {};

const columns = [{
  name: "Code",
  dataIndex: "id"
}, {
  name: "Name",
  dataIndex: "name"
}];

const arrFromApi = [{
  id: 1,
  name: "Marcus",
  age: "32"
}, {
  id: 2,
  name: "John",
  age: "30"
}, {
  id: 3,
  name: "Emily",
  age: "25"
}];

arrFromApi.forEach(item => {
  columns.forEach(column => {
    line[column.dataIndex] = item[column.dataIndex];
  })
  data.push(JSON.parse(JSON.stringify(line)));
});

console.log(data)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.