新日期作为反应关键道具?

时间:2018-07-25 17:05:52

标签: javascript reactjs

我有这个反应代码,其中我在某些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()}/>)               
  };
};

3 个答案:

答案 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中进行了描述:

  1. 在分配给数组条目时,您正在直接修改状态。您必须复制该数组并修改副本。

  2. 您正在使用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()) }并查看结果。