this is my code : codesandbox multiselect demo
I need to extract unique items from an array based on id and display resulting array as options. I'm using MUI Select component.
It works when I use this to create the new array with distinct id value:
dictinctItems.push(item);
But this doesn't work for some reason.
dictinctItems.push({ id: item.id, label: item.label });
Whats wrong with the second form?
CodePudding user response:
Because when you do dictinctItems.push(item);
you are pushing the reference of the same object into the list and when you do dictinctItems.push({ id: item.id, label: item.label });
you are pushing a new object every time.
In your component each time a new value is being selected you change the state in the handleChange
which will trigger a re-render, this re-render will again run your getDistinctItemsById
function at the top of the component and return a new list when you do dictinctItems.push({ id: item.id, label: item.label });
.
This can be fixed if you use useMemo
that is change
const dictinctItems = getDistinctItemsById(listData)
to
const dictinctItems = useMemo(() =>getDistinctItemsById(listData), [])
and you will always have the same objects on every re-render, no matter whether you use dictinctItems.push(item);
or dictinctItems.push({ id: item.id, label: item.label });
Just to make to understand a bit more about copying reference and value in javascript
Just look at this example below
let stringValue = 'Hi';
const objValue = {id: "1", label: 'P1'};
// for primitive value, it copy gets pushed to array
const myArray = [];
myArray.push(stringValue); // push copy of 'Hi' here
stringValue = 'Hi how are you'; // change 'Hi' to 'Hi how are you'
console.log(myArray[0]); // myArray still contains 'Hi'
// for objects, its reference gets pushed
const newArray = [];
newArray.push(objValue); // puts object reference into the array
objValue.id = "2"; // change 'id' property
console.log(newArray[0].id); // here id will be changed to '2'