我有这个反应代码,其中我在某些Input组件上使用new Date()。getTime()作为反应键道具。这可能是一种反模式,因为键需要稳定。但我想了解为什么这会导致错误。以及为什么将newDate()。getTime()作为键的行为要比Math.random()作为键的行为差。请查看以下两个示例以了解我的意思:
所讨论的代码类型:
class TextInputs extends React.Component {
state = {
textArray: ['hi,','My','Name','is']
};
handleChange = ({value, index}) => {
const {textArray} = this.state;
textArray[index] = value;
this.setState({textArray})
};
render(){
console.log(this.state.textArray)
return this.state.textArray.map((txt, i) => <Input onChange={this.handleChange} index={i} value={txt} key={new Date().getTime()}/>)
};
};
答案 0 :(得分:2)
您每次在渲染时都要更改关键点,从而破坏了反应中关键点的作用。该键旨在使React能够跟踪组件中的差异,以便它知道何时/何时重新渲染。在这种情况下,如果没有自然键,最好使用i
密钥需要保持一致。在此处阅读更多信息:https://reactjs.org/docs/lists-and-keys.html
答案 1 :(得分:1)
这可能是一种反模式,因为密钥需要稳定。
的确。 :-)
但是我想了解为什么这如此容易。以及为什么将newDate()。getTime()作为键的行为要比Math.random()作为键的行为差。
因为您可以在同一毫秒内呈现很多个元素。一毫秒对于人类来说是很长的时间。对于计算机,则没有那么多。因此,您最终得到的不是唯一的键。
在您(或任何阅读此书的人)尝试接触performance.now()
之前,请记住,正如您所说,按键必须稳定,performance.now()
的准确性也为某些人打开了大门。攻击,因此实施已退后(它确实非常精确,但不如最初预期的5微秒那么精确)。
旁注:此代码是错误的:
handleChange = ({value, index}) => {
const {textArray} = this.state;
textArray[index] = value;
this.setState({textArray})
};
该代码存在两个问题,均在文档的this page中进行了描述:
在分配给数组条目时,您正在直接修改状态。您必须复制该数组并修改副本。
您正在使用setState
的非回调版本根据现有状态设置状态。根据现有状态设置状态时,您必须使用setState
的回调版本。
理想情况下,根本不要为此使用数组索引;在对象上使用唯一的ID。但是,如果使用索引,则正确的代码应为:
handleChange = ({value, index}) => {
// Remember the string we're supposed to remove
const entry = this.state.textArray[index];
this.setState(({textArray}) => { // <== Note destructuring
// Find the first occurrence in the array as it is NOW (it may have changed)
const index = textArray.indexOf(entry);
// If the entry is still there...
if (index != -1) {
// ...create a copy of the array without it, return the state update
return {textArray: textArray.filter((e, i) => i !== index)};
// Or:
// textArray = textArray.slice();
// textArray.splice(index, 1);
// return {textArray};
// Or:
// return {textArray: [...textArray.slice(0, index), ...textArray.slice(index + 1)]};
}
});
};
答案 2 :(得分:1)
您的应用奇怪的原因是键不是唯一的。 new Date().getTime()
的分辨率为毫秒。当您在循环中执行此操作时,它的速度比一毫秒要快,因此某些项目会获得相同的键。
尝试在浏览器的控制台中运行for (let i = 0; i < 100; i++) { console.log((new Date).getTime()) }
并查看结果。