प्रतिक्रिया में फॉर्म लेबल के लिए अद्वितीय आईडी कैसे जनरेट करें?


128

मेरे पास labelएस के साथ तत्व हैं और मैं चाहता हूं कि विशेषताओं के labelसाथ तत्वों को जोड़ने के लिए अद्वितीय आईडी हो htmlFor। कुछ इस तरह:

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

मैं आईडी के आधार पर जनरेट करता था, this._rootNodeIDलेकिन यह 0.13 के बाद से उपलब्ध नहीं है। अब इसे करने का सबसे अच्छा और / या सरल तरीका क्या है?


यदि आप इस तत्व को बार-बार उत्पन्न कर रहे हैं, तो मैं एक बयान में मान रहा हूं कि इस पर पुनरावृत्त का उपयोग क्यों नहीं किया गया है? मुझे लगता है कि आप एक फ़ंक्शन को भी कॉल कर सकते हैं जो एक अद्वितीय गाइड उत्पन्न करता है यदि एक इंडेक्स नंबर पर्याप्त अच्छा नहीं है। stackoverflow.com/questions/105034/…
क्रिस हॉक्स

1
विभिन्न घटकों में कई अलग-अलग रूप तत्व होते हैं और उन सभी में विशिष्ट आईडी होनी चाहिए। आईडी जनरेट करने के लिए फंक्शन वही है जिसके बारे में मैंने सोचा था और अगर कोई बेहतर समाधान नहीं सुझाता है तो मैं क्या करने वाला हूं।
आर्टेम सेपगिन

3
आप "ग्लोबल" इंक्रीमेंटिंग काउंटर को कहीं स्टोर कर सकते हैं और उसका उपयोग कर सकते हैं। id = 'unique' + (++GLOBAL_ID);कहाँ var GLOBAL_ID=0;?
वायर्डप्रैरी

1
मुझे पता है कि मैं इस पार्टी में बहुत देर से जा रहा हूं, लेकिन एक और विकल्प आईडी का उपयोग करने के बजाय लेबल में इनपुट को लपेटना है, जैसे:<label>My label<input type="text"/></label>
माइक डेसजार्डिंस

जवाबों:


85

यह समाधान मेरे लिए ठीक काम करता है।

utils/newid.js:

let lastId = 0;

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

और मैं इसे इस तरह से उपयोग कर सकता हूं:

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

लेकिन यह आइसोमॉर्फिक ऐप में काम नहीं करेगा।

17.08.2015 को जोड़ा गया । कस्टम newId फ़ंक्शन के बजाय आप lodash से uniqueId का उपयोग कर सकते हैं ।

28.01.2016 को अपडेट किया गया । आईडी जनरेट करना बेहतर है componentWillMount


3
क्योंकि यह ब्राउज़र में पहली बार फिर से आईडी जनरेट करना शुरू कर देगा। लेकिन वास्तव में आप सर्वर और ब्राउज़र पर विभिन्न उपसर्गों का उपयोग कर सकते हैं।
आर्टेम सेपगिन

7
ऐसा मत करो render! में आईडी बनाएंcomponentWillMount
sarink

1
आपने एक स्टेटफुल कंटेनर बनाया है, लेकिन सेटस्टेट का उपयोग करने की उपेक्षा कर रहे हैं और इसके लिए कल्पना का उल्लंघन कर रहे हैं renderfacebook.github.io/react/docs/component-specs.html । हालांकि इसे ठीक करना बहुत आसान होना चाहिए।
ऐज

3
मैं कंस्ट्रक्टर में लॉश से यूनिक आई का उपयोग कर रहा हूं और आईडी को सेट करने के लिए सेटस्टेट का उपयोग कर रहा हूं। मेरे ग्राहक के लिए अच्छी तरह से काम करता है केवल app।
क्रॉसप्रोडक्ट

1
componentWillMountपदावनत किया जाता है, इसके बजाय निर्माणकर्ता में करें। देखें: reactjs.org/docs/react-component.html#unsafe_componentwillmount
Vic

78

आईडी को कंपोनेंटवैलमाउंट (2018 के लिए अपडेट) के अंदर रखा जाना चाहिए constructor, न कि render। इसे डालने से renderअनावश्यक रूप से नई आईडी फिर से जेनरेट होंगी।

यदि आप अंडरस्कोर या लॉश का उपयोग कर रहे हैं uniqueId, तो एक फ़ंक्शन है, इसलिए आपका परिणामी कोड कुछ इस तरह होना चाहिए:

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 हुक अपडेट:

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

11
या आप इसे कंस्ट्रक्टर में भी डाल सकते हैं।
जॉन वीज़्ज़

घटकWillMount रिएक्ट 16.3.0 के बाद से पदावनत है, इसके बजाय UNSAFE_componentWillMount का उपयोग करें, Reajs.org/docs/react-component.html#unsafe_componentwillmount पर
lokers

2
क्या कोई सुझाव दे सकता है कि रिएक्ट 16.8 में नए हुक के साथ यह कैसे किया जाना चाहिए?
ऐसिली

4
आप आईडी का मूल्य ट्रैक नहीं कर रहे हैं, आप भी उपयोग कर सकते हैंconst {current: id} = useRef(_uniqueId('prefix-'))
forivall

1
उपयोग स्टेट के बजाय यूज़ रीफ के उपयोग से क्या अंतर है?
XPD

24

2019-04-04 तक के बाद, यह रिएक्ट हुक के साथ पूरा किया जा सकता है 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

जैसा कि मैं इसे समझता हूं, आप सरणी विनाश में दूसरे सरणी आइटम को अनदेखा करते हैं जो आपको अपडेट करने की अनुमति देगा id, और अब आपको एक मूल्य मिला है जो घटक के जीवन के लिए फिर से अपडेट नहीं किया जाएगा।

का मान वह idहोगा myprefix-<n>जहां <n>से एक वृद्धिशील पूर्णांक मान लौटाया जाता है uniqueId। यदि यह आपके लिए पर्याप्त नहीं है, तो अपने जैसा बनाने पर विचार करें

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

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

या मेरे द्वारा यहां प्रकाशित लाइब्रेरी को देखें : https://github.com/rpearce/simple-uniqueid । वहाँ भी सैकड़ों या हजारों अन्य अद्वितीय आईडी चीजें हैं, लेकिन uniqueIdएक उपसर्ग के साथ लॉश को काम पूरा करने के लिए पर्याप्त होना चाहिए।


अपडेट 2019-07-10

आलसी प्रारंभिक अवस्था को इंगित करने के लिए @ ह्वॉन्ग एचके को धन्यवाद , जिसका योग यह है कि आप एक फ़ंक्शन पास कर सकते हैं जो useStateकेवल शुरुआती माउंट पर चलाया जाएगा।

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

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

1
मुझे सर्वर रेंडरिंग के साथ भी यही समस्या है, इस पृष्ठ पर बताए गए कई अन्य तरीके: घटक ब्राउज़र में एक नई आईडी के साथ रेंडर करेगा।
Artem Sapegin

@ArtemSapegin: रिएक्ट प्रोजेक्ट पर एक मुद्दा ( github.com/facebook/react/issues/1137 ) था जिसमें घटकों के यूनिक आईडी होने के कुछ तरीकों पर चर्चा की गई थी, लेकिन मुझे नहीं लगता कि इसमें से कुछ आया था। यह कितना महत्वपूर्ण है कि उत्पन्न आईडी सर्वर और क्लाइंट के बीच समान हैं? मुझे लगता है कि एक के लिए <input />, जो मायने रखता है वह यह है कि विशेषताओं htmlForऔर idविशेषताओं को एक साथ बांध दिया जाना चाहिए चाहे कोई भी मूल्य हो।
rpearce

यह अनावश्यक डोम अपडेट से बचने के लिए महत्वपूर्ण है, जो नई आईडी का कारण होगा।
आर्टेम सेपगिन

6
यह बेहतर है यदि आप किसी फ़ंक्शन के परिणाम के बजाय initialState# 1 के रूप में एक फ़ंक्शन प्रदान करते हैं const [ id ] = useState(() => uniqueId('myprefix-'))# 2 const [ id ] = useState(uniqueId('myprefix-')) राज्य: idऊपर दिए गए 2 तरीके अलग नहीं हैं। लेकिन अलग को uniqueId('myprefix-')हर री-रेंडर किए गए (# 2) के बजाय एक बार (# 1) निष्पादित किया जाएगा। देखें: आलसी प्रारंभिक अवस्था: reactjs.org/docs/hooks-reference.html#lazy-initial-state महंगी वस्तुओं का निर्माण कैसे करें ?: reactjs.org/docs/…
Huong

1
@Hongongk यह अद्भुत है; मुझे नहीं पता था! मैं अपना उत्तर अपडेट करूंगा
2

4

आप इसके लिए नोड-यूआईडी जैसी लाइब्रेरी का उपयोग कर सकते हैं ताकि यह सुनिश्चित किया जा सके कि आपको अद्वितीय आईडी मिले।

का उपयोग कर स्थापित करें:

npm install node-uuid --save

फिर अपनी प्रतिक्रिया घटक में निम्नलिखित जोड़ें:

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

3
अशुद्ध renderका उल्लंघन करती है facebook.github.io/react/docs/component-specs.html
aij

2
लगता है कि उत्तर को युक्ति के अनुपालन के लिए अद्यतन किया गया है
जोनास बर्लिन

2
यह आइसोमॉर्फिक ऐप्स में काम नहीं करता है, क्योंकि सर्वर पर उत्पन्न आईडी क्लाइंट पर उत्पन्न आईडी से अलग है।
डैनियल टी।

2
लेकिन यह जवाब के हिस्से के रूप में कहा गया है, जो बहुत ही भ्रामक है
टॉम मैकेंजी

1
हां, -1 UNIVERSALLY की अनोखी आईडी का उपयोग करने के लिए, यह एक विश्व आकार के नाखून के लिए ब्रह्मांड के आकार का हथौड़ा है।
जॉन z

1

उम्मीद है कि यह किसी के लिए एक सार्वभौमिक / आइसोमोर्फिक समाधान की तलाश में आने में मददगार है, क्योंकि चेकसम इश्यू ने मुझे पहले स्थान पर ला दिया है।

जैसा कि ऊपर कहा गया है, मैंने क्रमिक रूप से एक नई आईडी बनाने के लिए एक सरल उपयोगिता बनाई है। चूंकि आईडी सर्वर पर वेतन वृद्धि जारी रखते हैं, और क्लाइंट में 0 से शुरू होता है, इसलिए मैंने प्रत्येक SSR शुरू होने वाली वेतन वृद्धि को रीसेट करने का निर्णय लिया।

// utility to generate ids
let current = 0

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

export function resetIdCounter () { current = 0 }

और फिर रूट कंपोनेंट के कंस्ट्रक्टर या कंपोनेंटविलामाउंट में, रीसेट को कॉल करें। यह अनिवार्य रूप से प्रत्येक सर्वर रेंडर में सर्वर के लिए JS स्कोप को रीसेट करता है। क्लाइंट में इसका कोई प्रभाव नहीं पड़ता (और नहीं होना चाहिए)।


यदि ग्राहक फिर से 0 से नामकरण शुरू करते हैं तो आपके पास अभी भी आईडी क्लैश हो सकते हैं।
टॉमाज़ मूलार्क

@ टॉमाज़ आप चाहते हैं कि क्लाइंट फॉर्म 0 पर वापस शुरू हो ताकि चेकसम से मिलान हो सके।
टेनॉर 528

0

के सामान्य उपयोग के लिए labelऔर input, इस तरह से इनपुट को इनपुट में लपेटना आसान है:

import React from 'react'

const Field = props => (
  <label>
    <span>{props.label}</span>
    <input type="text"/>
  </label>
)      

यह मूल तत्व में पैडिंग लागू करने के लिए चेकबॉक्स / रेडियोबुटन में भी संभव बनाता है और इनपुट पर क्लिक की प्रतिक्रिया प्राप्त कर रहा है।


1
कुछ मामलों के लिए आसान और उपयोगी के लिए +1, उदाहरण के लिए उपयोगी नहीं, -1 select, विभिन्न पदों पर कई-लेबल, अनउपल्ड यूआई घटकों आदि, आईडी का उपयोग करने की भी a11y सिफारिश की जाती है: आमतौर पर, स्पष्ट लेबल सहायक तकनीक द्वारा बेहतर समर्थित होते हैं, w3। org / WAI / ट्यूटोरियल / फॉर्म / लेबल /…
माइकल बी।

-1

मुझे इस तरह से एक आसान समाधान मिला:

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


-1

मैं एक अद्वितीय जनरेटर मॉड्यूल (टाइपस्क्रिप्ट) बनाता हूं:

const uniqueId = ((): ((prefix: string) => string) => {
  let counter = 0;
  return (prefix: string): string => `${prefix}${++counter}`;
})();

export default uniqueId;

और अनन्य आईडी बनाने के लिए शीर्ष मॉड्यूल का उपयोग करें:

import React, { FC, ReactElement } from 'react'
import uniqueId from '../../modules/uniqueId';

const Component: FC = (): ReactElement => {
  const [inputId] = useState(uniqueId('input-'));
  return (
    <label htmlFor={inputId}>
      <span>text</span>
      <input id={inputId} type="text" />
    </label>
  );
};     

-3

अगर आपको जरूरत नहीं है, तो आईडी का उपयोग न करें, इसके बजाय इनपुट को इस तरह लेबल में लपेटें:

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

फिर आपको यूनिक आईडी के बारे में चिंता करने की आवश्यकता नहीं होगी।


2
यद्यपि यह एचटीएमएल 5 द्वारा समर्थित है, लेकिन इसे एक्सेसिबिलिटी के लिए हतोत्साहित किया जाता है: "हालांकि ऐसे मामलों में भी, इसे विशेषता के लिए सेट करने के लिए सबसे अच्छा अभ्यास माना जाता है क्योंकि कुछ सहायक प्रौद्योगिकियां लेबल और विजेट के बीच निहित संबंधों को नहीं समझती हैं।" - developer.mozilla.org/en-US/docs/Learn/HTML/Forms/… से
GuyPaddock

1
यह तरीका है जिस तरह से Reacts
ब्लेक

1
@BlakePlumb React टीम में एक सुलभ फॉर्म सेक्शन भी है: reactjs.org/docs/accessibility.html#accessible-forms
Vic
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.