新日期作为react关键props?

IT技术 javascript reactjs
2021-05-13 20:43:55

我有这个react代码,我在其中使用 new Date().getTime() 作为某些 Input 组件上的react键props。这可能是一个反模式,因为键需要稳定。但我想了解为什么这会如此糟糕。以及为什么 newDate().getTime() 作为 key 的表现比 Math.random() 作为 key 更糟糕。请查看这两个示例以了解我的意思:

有问题的代码类型:

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个回答

每次渲染时您都在更改密钥,从而破坏了react中密钥的目的。关键是允许 React 跟踪组件中的差异,以便它知道什么/何时重新渲染。在这种情况下,如果您没有自然键,最好使用i

密钥需要一致。在此处阅读更多信息:https : //reactjs.org/docs/lists-and-keys.html

这可能是一种反模式,因为密钥需要稳定。

的确。:-)

但我想了解为什么这会如此糟糕。以及为什么 newDate().getTime() 作为 key 的表现比 Math.random() 作为 key 更糟糕。

因为您可以在同一毫秒内渲染大量元素。一毫秒对人类来说是很长的时间。对计算机来说,不是那么多。所以你最终得到的键不是唯一的。

在您(或任何阅读本文的人)想要尝试之前performance.now(),请记住,正如您所说,密钥需要稳定,而且performance.now()的准确性为某些攻击打开了大门,因此实现已经退缩(它仍然非常精确,但不准确到它最初应该是的 5 微秒)。


旁注:这段代码是错误的:

handleChange = ({value, index}) => {
  const {textArray} = this.state;
  textArray[index] = value;
  this.setState({textArray})
};

该代码有两个问题,均在文档中的此页面上进行了描述:

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

您的应用程序行为异常的原因是键不是唯一的。的分辨率new Date().getTime()为毫秒。当您在循环中执行此操作时,它比一毫秒快,因此某些项目获得相同的键。

尝试for (let i = 0; i < 100; i++) { console.log((new Date).getTime()) }在浏览器的控制台中运行并查看结果。