【问题标题】:React: using index as key for items in the listReact:使用索引作为列表中项目的键
【发布时间】:2020-04-18 10:33:34
【问题描述】:

使用索引作为列表中项目的键有哪些缺陷?在添加或删除列表中的元素时,React 更改检测或任何意外列表更新是否存在任何性能缺陷。我已经阅读了几篇关于此的文章,但仍然不清楚。

请参考codepen

为什么在列表开头添加项目会导致上述代码笔出现意外行为?

另外,据说默认情况下,当没有传递 key 时,react 将 index 作为 key 传递。这意味着不传递任何键并将索引作为键传递 - 两者是同一回事?

【问题讨论】:

标签: reactjs


【解决方案1】:

这个问题以前有人问过,

但主要答案可以在Docs of React中找到

我们不建议使用索引作为键,如果项目的顺序可能 改变。这可能会对性能产生负面影响,并可能导致问题 与组件状态。查看 Robin Pokorny 的文章 深入解释使用指数作为指标的负面影响 钥匙。如果您选择不为列表项分配显式键,则 React 将默认使用索引作为键。

添加或删除元素时没有意外的列表更新

但主要原因还是后面的索引和比较算法,

您可以在“不同类型”下阅读here

这里的关键是要理解并非 DOM 中的所有内容都在 React“虚拟 DOM”中具有表示形式,并且因为对 DOM 的直接操作(例如用户更改值或监听元素的 jQuery 插件)不会被React,不使用唯一和常量键将导致 React 在键不恒定时重新创建组件的 DOM 节点(并丢失节点中的任何未跟踪状态),或者在键不是时重用 DOM 节点来渲染另一个组件唯一的(并将其状态绑定到其他组件)。

Here你有一个现场演示显示结果是多么糟糕

只需添加一个项目,更改它,添加更多项目,看看会发生什么。

也阅读here

【讨论】:

    【解决方案2】:

    您是对的,使用索引作为键可能会出现问题,但请注意我是说我们会遇到问题,但并非总是如此。如果我们不从列表中添加/删除项目,那么可以使用索引作为键,否则使用一些唯一标识项目的 id 会很好。原因是如果您从列表中添加或删除某些项目,旧项目的索引会更改,并且反应可能会混淆哪些项目已更改。性能方面,我认为这没有任何区别

    【讨论】:

      【解决方案3】:

      假设你正在渲染这个数组:

      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}}
      

      【讨论】:

        【解决方案4】:

        请参阅React documentation,了解列表和键,以及它们为何重要:

        键帮助 React 识别哪些项目已更改、添加或删除。应该为数组内的元素提供键,以使元素具有稳定的标识。

        它还说了一些关于使用索引作为键的事情,以及为什么不应该使用它:

        如果项目的顺序可能发生变化,我们不建议对键使用索引。这会对性能产生负面影响,并可能导致组件状态出现问题。查看 Robin Pokorny 的文章an in-depth explanation on the negative impacts of using an index as a key。如果您选择不为列表项分配显式键,那么 React 将默认使用索引作为键。 如果您有兴趣了解更多信息,这里是in-depth explanation about why keys are necessary

        【讨论】:

          【解决方案5】:

          如果键是索引,则重新排序项目会更改它。因此,组件状态可能会混淆,并可能将旧密钥用于不同的组件实例。如果没有唯一键,React 无法区分元素是被删除还是只是内容被改变。一旦您重新排序或过滤数组,索引就不再是唯一的。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-12-30
            • 1970-01-01
            • 2020-10-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多