使用索引作为列表中项目的键有哪些陷阱?在添加或删除列表中的元素时,是否存在 React 更改检测或任何意外列表更新的性能缺陷。我已经阅读了几篇关于此的文章,但仍然没有弄清楚。
请参考codepen
为什么在列表的开头添加一个项目会导致上述 codepen 出现意外行为?
另外,据说默认情况下,当没有传递键时,react 将索引作为键传递。这意味着不传递任何键和传递索引作为键 - 两者是一回事吗?
使用索引作为列表中项目的键有哪些陷阱?在添加或删除列表中的元素时,是否存在 React 更改检测或任何意外列表更新的性能缺陷。我已经阅读了几篇关于此的文章,但仍然没有弄清楚。
请参考codepen
为什么在列表的开头添加一个项目会导致上述 codepen 出现意外行为?
另外,据说默认情况下,当没有传递键时,react 将索引作为键传递。这意味着不传递任何键和传递索引作为键 - 两者是一回事吗?
这个问题以前有人问过,
但主要答案可以在React Docs 中找到
如果项目的顺序可能发生变化,我们不建议对键使用索引。这会对性能产生负面影响,并可能导致组件状态出现问题。查看 Robin Pokorny 的文章,深入了解使用索引作为键的负面影响。如果您选择不为列表项分配显式键,那么 React 将默认使用索引作为键。
添加或删除元素时没有意外的列表更新
但造成这种情况的主要原因是后面的索引和比较算法,
你可以看到这个在这里下的不同类型“
这里的关键是要理解并非 DOM 中的所有内容都在 React “Virtual DOM”中有表示,并且因为对 DOM 的直接操作(例如用户更改值或 jQuery 插件监听元素)不会被 React 注意到,而不是使用唯一键和常量键最终会导致 React 在键不恒定时重新创建组件的 DOM 节点(并丢失节点中的任何未跟踪状态),或者当键不唯一时重用 DOM 节点来呈现另一个组件(并且将其状态绑定到另一个组件)。
这里有一个现场演示,展示了结果有多糟糕
只需添加一个项目,更改它,添加更多项目,然后看看会发生什么。
有一个读这里太
您说得对,使用索引作为键可能会出现问题,但请注意,我是说我们可能会遇到问题,但并非总是如此。如果我们不从列表中添加/删除项目,那么可以使用索引作为键,否则使用一些唯一标识项目的 id 会很好。原因是如果您从列表中添加或删除一些项目,旧项目的索引会发生变化,并且react可能会混淆哪些项目发生了变化。性能方面我认为没有任何区别
假设您正在渲染这个数组:
const data = [{
name: 'riderOne',
time: 10, // let's assume it's timestamp
},{
name: 'riderTwo',
time: 11, // let's assume it's timestamp
},{
name: 'riderTwo',
time: 12, // let's assume it's timestamp
}];
现在假设我们有一个过滤器,用户可以使用它来选择完成比赛所需的时间,可以在“秒”、“分钟”和“小时”中显示。分钟可能是默认过滤器。因此,当您仅使用索引作为键并尝试将过滤器更改为“秒”或“小时”时,react将查看数据并假定数据未更改并且不会重新呈现列表。为了实现这一点,我们甚至为过滤器使用了唯一键。
key={`${item.id}-${filter}}
请参阅有关列表和键的React 文档,以及它们为何重要:
键可帮助 React 识别哪些项目已更改、添加或删除。应为数组内的元素提供键,以赋予元素稳定的身份。
它还说明了一些关于使用索引作为键的事情,以及为什么不应该使用它:
如果项目的顺序可能发生变化,我们不建议对键使用索引。这会对性能产生负面影响,并可能导致组件状态出现问题。查看 Robin Pokorny 的文章,深入了解使用索引作为键的负面影响。如果您选择不为列表项分配显式键,那么 React 将默认使用索引作为键。如果您有兴趣了解更多信息,这里有一个关于为什么需要密钥的深入解释。