Javascript how to create unique id on object that is pushed into an array

4.3k Views Asked by At

I want to push an object into an array a random amount of times and have each object have it's own unique id. Currently, I am able to push that object into the array a random amount of times but am getting "Each child in a list should have a unique "key" prop." error. When I console.log the array, I do see that every object has the same key.

I have some code set up to generate a unique ID, but it doesn't seem to work.

Here is my data object that I am calling:

let id = Math.random().toString(16).slice(2);

export const data = {
    key: id,
    asylumOffice: 'AyS',
    citizenship: 'h',
    raceOrEthnicity: 'other',
    caseOutcome: 'pending',
    completion: 'n',
    currentDate: 'f',
  };

And the code where I am calling it and generating a random amount:

let dataArray = [];
let randomNum = Math.floor(Math.random() * 10);
for (let i = 0; i < randomNum; i++) {
  dataArray.push(data);
} 

I understand that the for loop is pushing the same instance of data and that's why they all have the same id, but I don't know how to make it so that they each have their own. Any suggestions?

4

There are 4 best solutions below

1
ali ahmad On BEST ANSWER

simplelly call Math.floor(Math.random() * 10) on every push and use spread syntaxs

// changed let to const cause it's not re-assigned
const dataArray = [];
for (let i = 0; i < randomNum; i++) {
  // this copies the original data and overwrite key to a new randomly
  // generated key
  dataArray.push({ ...data, key: Math.floor(Math.random() * 10) });
}
1
Gabe On

If you want to generate really unique id’s, you should use uuid.

Here is the npm package. It is fairly easy to setup and use.

0
jsejcksn On

From the React docs for Lists and Keys:

The best way to pick a key is to use a string that uniquely identifies a list item among its siblings.

So keys don't need to be random: they just need to be unique amongst siblings. And for that reason, using a plain integer for a fixed key is just fine:

const count = Math.floor(Math.random() * 10);

const dataArray = [...new Array(count).keys()].map(key => ({...data, key}));
0
Scott Sauyet On

If you don't mind taking the chance of random number collision on the ids, then just spread new random ids into your objects as you build the array. I might do it like this:

const randomCopies = (data) => [...Array (Math .floor (Math .random () * 10))] .map(() => ({
  id: Math .random() .toString(16) .slice (2), 
  ... data
}))

const data = {asylumOffice: 'AyS',  citizenship: 'h',  raceOrEthnicity: 'other',  caseOutcome: 'pending', completion: 'n', currentDate: 'f'}

console .log (randomCopies (data))
.as-console-wrapper {max-height: 100% !important; top: 0}

But if this is just to avoid collisions, then a sequential number will be cleaner, and you could do this instead:

const seqNumber = ((n) => () => ++n) (0)

const randomCopies = (data) => [...Array (Math .floor (Math .random () * 10))] .map(() => ({
  id: seqNumber(), 
  ... data
}))

const data = {asylumOffice: 'AyS',  citizenship: 'h',  raceOrEthnicity: 'other',  caseOutcome: 'pending', completion: 'n', currentDate: 'f'}

console .log (randomCopies (data))
.as-console-wrapper {max-height: 100% !important; top: 0}

In either case, this will choose a random number of copies from 0 to 9. If you want from 1 to 10, then you will need to add 1 to the results of the Math.floor call.