The Bug π
I had to solve an issue with the order of items in a dropdown. The problem was that items in the dropdown were sorted wrongly (in a different way than from the server).
For example, data from the server were in this order:
const items = [{
id: "/product/id/2",
title: "product 2"
},
{
id: "/product/id/1",
title: "product 1"
},
{
id: "/product/id/4",
title: "product 4"
},
{
id: "/product/id/5",
title: "product 5"
},
];
There was a function which mapped that data from the server into an object, something like this:
function mapToObject(items) {
return items.reduce((acc, item) => {
acc[item.id] = item;
return acc;
}, {});
};
Because JavaScript (for objects) does not (always) follow the insertion order, the result of that function was:
{
"/product/id/1": {
id: "/product/id/1",
title: "product 1"
},
"/product/id/2": {
id: "/product/id/2",
title: "product 2"
},
"/product/id/4": {
id: "/product/id/4",
title: "product 4"
},
"/product/id/5": {
id: "/product/id/5",
title: "product 5"
}
}
The result of that function led to the wrong order of items in the dropdown.
Why does it happen? π
Property order in normal Objects is a complex subject in JavaScript.
While in ES5 explicitly no order has been specified, ES2015 defined an order in certain cases, and successive changes to the specification since have increasingly defined the order (even, as of ES2020, the for-in
loop's order). Given is theβ¦
The Solution π
I wanted to keep "similar structure" because the dropdown can have a lot of items (for example, I would have to iterate over all items to get a selected item) so I solved the issue with a Map object - guarantees the keys will be iterated in order of insertion and it has similar features like Object.
function toMappedItems(items) {
const map = new Map();
items.forEach(item => map.set(item.id, item));
return map;
}
The result of that new function is:
0: {"/product/id/2" => {id: "/product/id/2", ...}}
1: {"/product/id/1" => {id: "/product/id/1", ...}}
2: {"/product/id/4" => {id: "/product/id/4", ...}}
3: {"/product/id/5" => {id: "/product/id/5", ...}}
So it is easy to work with that result and it keeps the order of items from the server.
The whole problem and solution are "simplified". The main take away is to not rely on the order in Object. π
Top comments (0)