web-dev-qa-db-fra.com

Comment générer des identifiants uniques pour les étiquettes de formulaire dans React?

J'ai des éléments de formulaire avec labels et je veux avoir des identifiants uniques pour lier labels aux éléments avec l'attribut htmlFor. Quelque chose comme ça:

React.createClass({
    render() {
        const id = ???;
        return (
            <label htmlFor={id}>My label</label>
            <input id={id} type="text"/>
        );
    }
});

J'avais l'habitude de générer des identifiants basés sur this._rootNodeID, mais ceux-ci ne sont plus disponibles depuis React 0.13. Quelle est la meilleure et/ou la plus simple façon de le faire maintenant?

95
Artem Sapegin

Cette solution fonctionne bien pour moi.

utils/newid.js:

let lastId = 0;

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

Et je peux l'utiliser comme ça:

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"/>
        );
    }
});

Mais cela ne fonctionnera pas dans les applications isomorphes.

Ajouté le 17.08.2015. Au lieu de la fonction newId personnalisée, vous pouvez utiliser uniqueId de lodash.

Mise à jour le 28.01.2016. Il est préférable de générer un identifiant dans componentWillMount.

71
Artem Sapegin

L'identifiant doit être placé à l'intérieur de composantWillMount (mise à jour pour 2018) constructor, pas render. Le mettre dans render génèrera inutilement de nouveaux identifiants.

Si vous utilisez un trait de soulignement ou un lodash, il existe une fonction uniqueId. Votre code doit donc ressembler à ceci:

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>
  );
}
55
sarink

Il existe de nombreuses solutions de type "ruban adhésif" ... La première est https://github.com/DelvarWorld/Unique-Id-Mixin

4
Stan E

Vous pouvez utiliser une bibliothèque telle que node-uuid pour vous assurer que vous obtenez des identifiants uniques.

Installez en utilisant:

npm installer node-uuid --save

Ensuite, dans votre composant de réaction, ajoutez ce qui suit:

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>
    );
  }   
}
2
Stuart Ervine

En remontant au 2019-04-04, cela semble pouvoir être accompli avec les crochets de React ' 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

Si j'ai bien compris, vous ignorez le deuxième élément du tableau dans le processus de déstructuration du tableau qui vous permettrait de mettre à jour id. Maintenant, vous avez une valeur qui ne sera plus mise à jour pendant la durée de vie du composant.

La valeur de id sera myprefix-<n>, où <n> est une valeur entière incrémentielle renvoyée par uniqueId. Si cela ne vous suffit pas, envisagez de créer le vôtre comme

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

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

ou consultez la bibliothèque que j'ai publiée avec ceci ici: https://github.com/rpearce/simple-uniqueid . Il existe également des centaines ou des milliers d'autres identifiants uniques, mais la variable uniqueId de lodash avec un préfixe devrait suffire à lui permettre d'accomplir son travail.

2
rpearce

J'espère que cela sera utile à quiconque viendra à la recherche d'une solution universelle/isomorphe, car le problème de la somme de contrôle est ce qui m'a amené ici. 

Comme indiqué ci-dessus, j'ai créé un utilitaire simple permettant de créer séquentiellement un nouvel identifiant. Comme les identifiants continuent d’augmenter sur le serveur et de recommencer à zéro à partir du client, j’ai décidé de réinitialiser l’incrément à chaque démarrage du SSR.

// utility to generate ids
let current = 0

export default function generateId (prefix) {
  return `${prefix || 'id'}-${current++}`
}

export function resetIdCounter () { current = 0 }

Ensuite, dans le constructeur du composant racine ou composantWillMount, appelez la réinitialisation. Cela réinitialise essentiellement l'étendue JS du serveur dans chaque rendu de serveur. Chez le client, cela n’a (et ne devrait) avoir aucun effet.

1
tenor528

J'ai trouvé une solution facile comme celle-ci:

class ToggleSwitch extends Component {
  static id;

  constructor(props) {
    super(props);

    if (typeof ToggleSwitch.id === 'undefined') {
      ToggleSwitch.id = 0;
    } else {
      ToggleSwitch.id += 1;
    }
    this.id = ToggleSwitch.id;
  }

  render() {
    return (
        <input id={`prefix-${this.id}`} />
    );
  }
}
0
OZZIE

N'utilisez pas d'ID du tout si vous n'en avez pas besoin, mais insérez plutôt l'entrée dans une étiquette comme celle-ci:

<label>
   My Label
   <input type="text"/>
</label>

Dans ce cas, vous n'aurez plus à vous soucier des identifiants uniques.

0
Mike Desjardins