DEV Community

pranay rauthu
pranay rauthu

Posted on

uuid in JavaScript.

while working with array of components in react js application. react complains us to provide a unique value key prop to the list items. we get away with this warning by adding array index as key. But recently I got to know that this will actually lead to errors when you are updating the array(experienced personally in one of my project). so we need set a unique key other than array index.

After googling about the generating unique id, I got to know few solutions & tricks to generate uids.
I came up with following solution. I believe this will have a very less chance of producing a two unique values.

I've decided to generate an id based on following parameters.

  • time
  • randomness
  • counter

time: let's assume that we get a unique value with current time in ms.

new Date().getMilliseconds();
Enter fullscreen mode Exit fullscreen mode

for a better uniqueness. we can also use performance.now function. more info about performance.now can be found here.

randomness: random number can be generated by calling Math.random()

counter: By any chance if we get two unique numbers successively. Just for safety, we need a counter which resets after certain limit. a circular linked list will be able to to the job.

so putting all together.

    function uniqueId() {
        const firstItem = {
            value: "0"
        };
        /*length can be increased for lists with more items.*/
        let counter = "123456789".split('')
            .reduce((acc, curValue, curIndex, arr) => {
                const curObj = {};
                curObj.value = curValue;
                curObj.prev = acc;

                return curObj;
            }, firstItem);
        firstItem.prev = counter;

        return function () {
            let now = Date.now();
            if (typeof performance === "object" && typeof performance.now === "function") {
                now = performance.now().toString().replace('.', '');
            }
            counter = counter.prev;
            return `${now}${Math.random().toString(16).substr(2)}${counter.value}`;
        }
    }

    const randomIdGenerator = uniqueId();

    randomIdGenerator(); // 3519936476425aaa4f2a048 
    randomIdGenerator(); // 3519936472474f1e8119427
    randomIdGenerator(); // 35199364800000017a40a2d1eaa226

Enter fullscreen mode Exit fullscreen mode

this stackoverflow thread has many more solutions.

Please comment below if you know any other techniques to generate uuid.

Top comments (6)

Collapse
 
bgadrian profile image
Adrian B.G. • Edited

UUID is pretty standard, and already has 5 version of algorithms. You do not need to invent a new one, just read the specs or use the npm package:

en.wikipedia.org/wiki/Universally_...
npmjs.com/package/uuid seems to respect the standard. Other tools like databases use it too (like MongoDB)

Beside your parameters (time and random number), you need another one, to avoid collision between 2 separate instances that reach the same random at the same time (I know that is far fetched ..), and the UUID uses something from the localhost (a mac address for instance).

You do not need a counter, as the 100s-nanoseconds interval and a good random number should be enough to avoid a collision. If you have a counter and only 1 machine generating it, you will not need anything else anyway. They will be unique in your system.

The paper is not so technical, I suggest reading it: tools.ietf.org/html/rfc4122
You will want a Random-based UUID, which is 4.

Collapse
 
wuz profile image
Conlin Durbin

This is a really interesting snippet for generating UUID's where you don't care about collisions. One note I haven't seen mentioned here is the danger in using Math.random() for this kind of thing. For more information on this, check this out: medium.com/@betable/tifu-by-using-...

Collapse
 
gerreth profile image
Gerret Halberstadt

If my component is related to a database object, I usually use its ID from there.

If you need to create a unique ID on the fly, I'd suggest npmjs.com/package/uuid

Collapse
 
marpme profile image
marpme (Marvin) • Edited

Actually, there are standards (RFC's) defining how to properly build a UUID:

en.wikipedia.org/wiki/Universally_...

Collapse
 
dreddergun profile image
Vyguzov Aleksandr

I can't figure out why do you need a chain with counters? Why you didn't just write
let counter: number = 0;
and further increment inside returning callback?
counter = counter++;

Collapse
 
layflags profile image
Lay Flags

github.com/ericelliott/cuid is also worth a look!