Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate unique IDs for form labels in React?

Tags:

reactjs

People also ask

How do I get a unique ID in React?

Approach: We will be using Uuid V4 in this tutorial. Uuid v4 is a React library or package that creates a universally unique identifier (UUID). It is a 128-bit unique identifier generator. The bits that comprise a UUID v4 are generated randomly and with no inherent logic.

Do React components have a unique ID?

Both react-async and react-multiplayer need components to have unique identifiers.

How do I make labels in react JS?

React has no for property for labels. It defined the htmlFor attribute. The reason is, that you are writing HTML code in JSX syntax. JSX is an extension to javascript which executes javascript code.

Why React keys should be unique?

Keys Must Only Be Unique Among SiblingsKeys serve as a hint to React but they don't get passed to your components. If you need the same value in your component, pass it explicitly as a prop with a different name: const content = posts.


The id should be placed inside of componentWillMount (update for 2018) constructor, not render. Putting it in render will re-generate new ids unnecessarily.

If you're using underscore or lodash, there is a uniqueId function, so your resulting code should be something like:

constructor(props) {
    super(props);
    this.id = _.uniqueId("prefix-");
}

render() { 
  const id = this.id;
  return (
    <div>
        <input id={id} type="checkbox" />
        <label htmlFor={id}>label</label>
    </div>
  );
}

2019 Hooks update:

import React, { useState } from 'react';
import _uniqueId from 'lodash/uniqueId';

const MyComponent = (props) => {
  // id will be set once when the component initially renders, but never again
  // (unless you assigned and called the second argument of the tuple)
  const [id] = useState(_uniqueId('prefix-'));
  return (
    <div>
      <input id={id} type="checkbox" />
      <label htmlFor={id}>label</label>
    </div>
  );
}

This solutions works fine for me.

utils/newid.js:

let lastId = 0;

export default function(prefix='id') {
    lastId++;
    return `${prefix}${lastId}`;
}

And I can use it like this:

import newId from '../utils/newid';

React.createClass({
    componentWillMount() {
        this.id = newId();
    },
    render() {
        return (
            <label htmlFor={this.id}>My label</label>
            <input id={this.id} type="text"/>
        );
    }
});

But it won’t work in isomorphic apps.

Added 17.08.2015. Instead of custom newId function you can use uniqueId from lodash.

Updated 28.01.2016. It’s better to generate ID in componentWillMount.


Following up as of 2019-04-04, this seems to be able to be accomplished with the React Hooks' useState:

import React, { useState } from 'react'
import uniqueId from 'lodash/utility/uniqueId'

const Field = props => {
  const [ id ] = useState(uniqueId('myprefix-'))

  return (
    <div>
      <label htmlFor={id}>{props.label}</label>
      <input id={id} type="text"/>
    </div>
  )      
}

export default Field

As I understand it, you ignore the second array item in the array destructuring that would allow you to update id, and now you've got a value that won't be updated again for the life of the component.

The value of id will be myprefix-<n> where <n> is an incremental integer value returned from uniqueId. If that's not unique enough for you, consider making your own like

function gen4() {
  return Math.random().toString(16).slice(-4)
}

function simpleUniqueId(prefix) {
  return (prefix || '').concat([
    gen4(),
    gen4(),
    gen4(),
    gen4(),
    gen4(),
    gen4(),
    gen4(),
    gen4()
  ].join(''))
}

or check out the library I published with this here: https://github.com/rpearce/simple-uniqueid. There are also hundreds or thousands of other unique ID things out there, but lodash's uniqueId with a prefix should be enough to get the job done.


Update 2019-07-10

Thanks to @Huong Hk for pointing me to hooks lazy initial state, the sum of which is that you can pass a function to useState that will only be run on the initial mount.

// before
const [ id ] = useState(uniqueId('myprefix-'))

// after
const [ id ] = useState(() => uniqueId('myprefix-'))

You could use a library such as node-uuid for this to make sure you get unique ids.

Install using:

npm install node-uuid --save

Then in your react component add the following:

import {default as UUID} from "node-uuid";
import {default as React} from "react";

export default class MyComponent extends React.Component {   
  componentWillMount() {
    this.id = UUID.v4();
  }, 
  render() {
    return (
      <div>
        <label htmlFor={this.id}>My label</label>
        <input id={this.id} type="text"/>
      </div>
    );
  }   
}