Array.push () always stacking the last forEach item
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"}]
However, if I replace my data.push(line)
with console.log(line)
it is printed in the console correctly each of the names the way I need:
[{id: 1, name: "Marcus"}, {id: 2, name: "John"}, {id: 3, name: "Emily"}]
Would anyone know say what's wrong with this scenario? Because I understand that if the console is printing in this sequence, then the final result of my array should be the same.
2 answers
What happens is that with each iteration you are overwriting the id
and name
of the line
object.
The correct would be to create a new object every 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 to 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
. By creating a new object with each iteration, you eliminate this problem.
Another Way is by converting the object line
to string 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 value independent 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 forEach
will have as its value the last object of the array arrFromApi
, i.e. {"id":3,"name":"Emily"}
, as said in the answer of hkotsubo.
In this case, you can keep your code as it is, just by changing the line of 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)