If you are using ES6-based JavaScript (with the `class` keyword). You cannot use mixins. I now recommend using the react-html-id npm module to solve this problem instead. It works very similarily to the older `unique-id-mixin`.

I’ve recently been using React as a framework for more advanced web development, and I love it, more about that in a future post.

A problem I’ve been having with React is how to do id tags properly. These are necessary for both label elements and many aria- bindings. For example:

render() {
  return (
    <div>
      <label htmlFor="nameInput">Please input your name</label>
      <input type="text"
             id="nameInput"
             placeholder="Full Name"
             value={name}
             onChange={this.handleFieldChange.bind(this, 'name')} />
    </div>
  )
}

If this is put in a reusable component, the IDs will be duplicated and the label will cease to function as intended.

I first tried a very simple approach. A function that returns an ever-increasing global counter and returned a new value value on every call (id-1, id-2, id-xxx etc.). This was not a good idea for one reason: It means every time render is called, all components will get new IDs. This ruins the concept of pure components, it is very inefficient and also it messes with the browser.

The fix for this is the Unique ID mixin. By including this mixin a unique id will be assigned tho the current component, and IDs for sub-components will then be derived from the parent’s ID. This also uses an incrementing counter, but the difference is that it’s scoped to the current component and the counter resets every update. So every render will result in the same IDs being assigned (assuming the order of elements is the same).

The above example would look like this using the unique ID mixin:

render() {
  return (
    <div>
      <label htmlFor={this.getNextHtmlFor()}>Please input your name</label>
      <input type="text"
             id={this.getNextHtmlFor()}
             placeholder="Full Name"
             value={name}
             onChange={this.handleFieldChange.bind(this, 'name')} />
    </div>
  )
}

Here we use the shortcut function getNextHtmlFor. This will return the same ID twice in a row, a simplification available for the most common scenario.

In many cases though, you either need the IDs in an interspersed order, making it impossible to call getNextHtmlFor twice in a row to get the ID. Or you need to use a single ID more than two times. Both these scenarios is solved by using getNextUid instead. This function requires you to pass a string and will then return a globally unique ID. The string you pass only need to be unique within the current component.

The following example demonstrates it’s use with a screen-reader only hint for an input field:

render() {
  let inputId = this.getNextUid('date-input'),
       hintId = this.getNextUid('date-hint');
  return (
    <div>
      <label htmlFor={inputId}>Please input a date</label>
      <span className="sr-only" id={hintId}>The date should be input on the format YYYY-MM-DD</span>
      <input type="text"
             id={inputId}
             aria-describedby={hintId}
             placeholder="YYYY-MM-DD"
             value={date}
             onChange={this.handleFieldChange.bind(this, 'date')} />
    </div>
  )
}

Edit July 2016: Fixed some grammar.