我的表单元素包含label
,我希望使用唯一ID将label
链接到具有htmlFor
属性的元素。像这样:
React.createClass({
render() {
const id = ???;
return (
<label htmlFor={id}>My label</label>
<input id={id} type="text"/>
);
}
});
我曾经根据this._rootNodeID
生成ID,但自React 0.13起它无法使用。现在最好和/或最简单的方法是什么?
答案 0 :(得分:78)
此解决方案适用于我。
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 。您可以使用lodash中的uniqueId代替自定义newId函数。
已于2016年1月28日更新。最好在componentWillMount
生成ID。
答案 1 :(得分:57)
id应该放在 componentWillMount (2018年更新)constructor
内,而不是render
。将其放入render
将不必要地重新生成新的ID。
如果您使用下划线或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>
);
}
答案 2 :(得分:2)
您可以使用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>
);
}
}
答案 3 :(得分:2)
自2019年4月4日起,这似乎可以通过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东西,但是lodash的带有前缀的uniqueId
应该足以完成工作。
答案 4 :(得分:1)
希望这对任何想要寻找通用/同构解决方案的人都有帮助,因为校验和问题首先引起了我的兴趣。
如上所述,我创建了一个简单的实用程序来顺序创建一个新的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中,调用reset。这实质上重置了每个服务器渲染中服务器的JS范围。在客户端,它没有(并且不应该)有任何影响。
答案 5 :(得分:1)
我创建一个uniqueId生成器模块(Typescript):
const uniqueId = ((): ((prefix: string) => string) => {
let counter = 0;
return (prefix: string): string => `${prefix}${++counter}`;
})();
export default uniqueId;
并使用顶部模块生成唯一的ID:
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>
);
};
答案 6 :(得分:0)
对于label
和input
的通常用法,将输入包装到这样的标签中会更容易:
import React from 'react'
const Field = props => (
<label>
<span>{props.label}</span>
<input type="text"/>
</label>
)
这还使得可以在复选框/单选按钮中将填充应用于根元素,并且仍然获得单击输入的反馈。
答案 7 :(得分:-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}`} />
);
}
}
答案 8 :(得分:-2)
Don't use IDs at all if you don't need to, instead wrap the input in a label like this:
<label>
My Label
<input type="text"/>
</label>
Then you won't need to worry about unique IDs.