1

I am trying to implement a Set on the dropdown list object and within the Set, I am using map function . I have tried two different ways by using Set but there has been no removal of the duplicates. Here, devices is the object and from there am trying to execute Set with map function. devices is the object.

enter image description here

Here is the dropdown list which is showing repeated values. On the right hand-side , you can see the devices array being shown. The dropdown list should show 4-5 options of device_id. Please help. enter image description here

  • 1
    Please share your code as text, not as an image. We can't copy the code in your image into our answers – Nick Parsons Apr 15 '23 at 09:08
  • const Devdropdown = () => { const [devices, setDevices] = useState([]); useEffect(() => { async function getDevices() { const response = await fetch(url); const body = await response.json(); setDevices(body.data); } getDevices(); }, []); – Ankan Chanda Apr 15 '23 at 09:24
  • return (

    Devices

    ); };
    – Ankan Chanda Apr 15 '23 at 09:24
  • It's a bit hard to read in the comments, are you able to please [edit] your question to include it in a formatted way? – Nick Parsons Apr 15 '23 at 09:34

1 Answers1

2

Sets don't remove objects that have different references. Even if the object has the same values these objects aren't considered the same:

const arr = [
  // These objects look the same but are both unique objects in memory, so they have different references
  {foo: 1},
  {foo: 1}
];

const res = [...new Set(arr)];
console.log(res); // [{foo: 1}, {foo: 1}]

Your case is similar to the above example, as the JSX <option ...></option> are creating objects behind the scenes.

Instead, I suggest that you use a different method to deduplicate your devices array from the duplicate objects. You can perform this deduplication only when your devices array changes with the help of useMemo() (assuming devices is state), for example:

const uniqueDevices = useMemo(() => {
   const uniqueMap = new Map(devices.map(device => [
     device.device_id, // deduplicate by the `device_id` property
     device
   ]);
   return [...uniqueMap.values()];
}, [devices]);

// please post your code as text so we don't have to retype this :)
return <div>
  <h1>Devices</h1>
  <select>
    { devices ?
      ? uniqueDevices.map(device => <option key={device.device_id}>{device.device_id}</option>)
      : null
    }
  </select>
</div>

If you only need to refer to the device_id property in your JSX from each device object, then you can continue to use a Set() to remove your duplicates as @andrew suggests, eg:

const uniqueDeviceIds = useMemo(() => 
  Array.from(new Set(devices.map(device => device.device_id)))
, [devices]);

return <div>
  <h1>Devices</h1>
  <select>
    { devices ?
      ? uniqueDeviceIds.map(deviceId => <option key={deviceId}>{device_id}</option>)
      : null
    }
  </select>
</div>
Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
  • You could also use a [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) as opposed to a Map, which has unique items by design – andrew Apr 15 '23 at 09:24
  • @andrew But only unique primitives, not objects. We could map it to an array of `device_id`s if OP only needs the `device_id` property in the JSX though – Nick Parsons Apr 15 '23 at 09:26
  • I guess you'd have to use the Set as a hashmap though so a Map may be more convenient in this case‍♂️ – andrew Apr 15 '23 at 09:27
  • @andrew I guess it depends on OPs case, we (most likely) can't do `[...new Set(devices)]` unfortunately due to each object being a unique reference in `devices`, but we take map the array to an array of deviceIds which we can then remove the duplicates from with a `Set`, I've provided an example now with that as an option. Thanks – Nick Parsons Apr 15 '23 at 09:33
  • I have used Set like this: (1) {devices?.map((device, value) => { return [...new Set(device, value)].map((device, value) => { //console.log(device); return ( ); }); })} (2){devices ? [ ...new Set( devices.map((device, idx) => { return ; }) ), ] : null} – Ankan Chanda Apr 15 '23 at 09:33
  • And after using the above two Set ways, it is still giving the repeated elements. – Ankan Chanda Apr 15 '23 at 09:36
  • @AnkanChanda Yes, (1) isn't a valid way of using a Set as you're passing a single object to it, a `Set()` doesn't accept 2 arguments, it just accepts 1, so `value` won't do anything. I have explained why (2) doesn't work in my answer above, `` doesn't create a unique object, so it's not considered the same as the others so the Set won't remove it. See my answer above for the approach you should take instead. – Nick Parsons Apr 15 '23 at 09:38
  • 1
    Thank you so much Nick and Andrew. It did get solved by implementing useMemo. And yes, next time onwards I will give the code in text format. – Ankan Chanda Apr 15 '23 at 09:40