[reactjs] React에서 양식 레이블에 대한 고유 ID를 생성하는 방법은 무엇입니까?

labels 가있는 양식 요소가 있고 s labelhtmlFor속성 이있는 요소 에 연결하는 고유 ID를 갖고 싶습니다 . 이 같은:

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

나는 기반으로 ID를 생성 this._rootNodeID했지만 React 0.13 이후로는 사용할 수 없습니다. 지금 가장 좋고 / 또는 가장 간단한 방법은 무엇입니까?



답변

이 솔루션은 저에게 잘 작동합니다.

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 를 사용할 수 있습니다 .

업데이트 : 2016 년 1 월 28 일 . .NET에서 ID를 생성하는 것이 좋습니다 componentWillMount.


답변

ID는 .NET이 아닌 componentWillMount (2018 년 업데이트) 내에 있어야합니다 . 그것을 넣으면 불필요하게 새 ID가 다시 생성됩니다.constructorrenderrender

밑줄이나 lodash를 사용하는 경우 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 Hooks 업데이트 :

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


답변

2019-04-04에 이어 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

내가 이해했듯이, 당신은 업데이트를 허용하는 배열 분해의 두 번째 배열 항목을 무시 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 에서 게시 한 라이브러리를 확인 하십시오 . 또한 수백 또는 수천 개의 다른 고유 ID가 있지만 uniqueId접두사가있는 lodash 는 작업을 완료하기에 충분합니다.


업데이트 2019-07-10

@Huong Hk에게 게으른 초기 상태연결 하도록 알려 주셔서 감사합니다. 이의 합계 useState는 초기 마운트에서만 실행 되는 함수를 전달할 수 있다는 것입니다.

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

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


답변

이를 위해 node-uuid 와 같은 라이브러리를 사용하여 고유 한 ID를 얻을 수 있습니다.

다음을 사용하여 설치 :

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


답변

체크섬 문제가 처음부터 나를 이끈 이유이기 때문에 범용 / 동형 솔루션을 찾는 모든 사람에게 도움이되기를 바랍니다.

위에서 말했듯이 순차적으로 새 ID를 만드는 간단한 유틸리티를 만들었습니다. ID는 서버에서 계속 증가하고 클라이언트에서 0부터 다시 시작하기 때문에 SSR이 시작될 때마다 증가분을 재설정하기로 결정했습니다.

// utility to generate ids
let current = 0

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

export function resetIdCounter () { current = 0 }

그런 다음 루트 구성 요소의 생성자 또는 componentWillMount에서 재설정을 호출합니다. 이것은 본질적으로 각 서버 렌더링에서 서버의 JS 범위를 재설정합니다. 클라이언트에서는 효과가 없습니다.


답변

label및 의 일반적인 사용법의 경우 다음 과 input같이 입력을 레이블로 래핑하는 것이 더 쉽습니다.

import React from 'react'

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

또한 체크 박스 / 라디오 버튼에서 패딩을 루트 요소에 적용하고 여전히 입력에 대한 클릭 피드백을받을 수 있습니다.


답변

다음과 같은 쉬운 해결책을 찾았습니다.

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