【问题标题】:ReactJS : What is the best way to give keys in array elementReactJS:在数组元素中给出键的最佳方法是什么
【发布时间】:2018-04-15 10:50:34
【问题描述】:

我刚开始使用 ReactJS 并尝试了其他类似问题的解决方案,但到目前为止还没有运气。

这是我的工作代码:

import React from 'react';
import ReactDOM from 'react-dom';


const Numbers = ['2', '4', '6', '8'];

const NumbersList = (props) => (
   <ul>
      {
          props.Numbers.map (
             number => <li key={number}>{number * 2}</li>
          )
      }
    </ul>
)
ReactDOM.render(<NumbersList Numbers = {Numbers} />, document.getElementById('root') )

但是当我将数字数组传递为:

const Numbers = ['4', '4', '6', '8']

我收到此错误:

警告:遇到两个孩子使用相同的密钥,4。密钥应该是唯一的,以便组件在更新时保持其身份。

所以我的问题是:在这种情况下提供钥匙的最佳方式是什么?如果我使用数字(如上例)作为键,避免此警告的最佳解决方案是什么?

谢谢!

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    当您没有项目的明确唯一属性(非唯一基元列表)时,您可以使用索引。

    注意:如果项目具有唯一的 id(并且非原始列表应该),则不要使用索引,因为它是 anti-pattern

    const Numbers = ['2', '4', '4', '8'];
    
    const NumbersList = (props) => (
      <ul>
      {
      props.Numbers.map (
        (number, index) => <li key={index}>{number * 2}</li>
      )}
      </ul>
    )
    
    ReactDOM.render(
      <NumbersList Numbers = {Numbers} />,
      document.getElementById('root')
    )
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <div id="root"></div>

    【讨论】:

    • 但是根据官方文档,我们不建议使用索引对吗?那么作为初学者保持良好的实践,还有其他方法可以实现吗?
    • 看看我添加的注释。通常你会渲染一个对象列表,每个对象都应该有一个唯一的属性来用作键。在这种情况下,您没有其他选择,因为这些值不是唯一的。
    • 所以如果我们没有唯一值,我唯一的解决方案就是将索引作为键?如果我们有动态值并且它们不是唯一的怎么办?请原谅我的初级问题。
    • 您可以映射数组并为每个项目生成一个具有唯一键的对象,并且每当您添加项目时,将其添加为具有唯一键的对象。
    • 它似乎有效。你可以分享jsfiddle吗?谢谢!
    【解决方案2】:

    原因是每个&lt;li&gt; 标签都应该有一个唯一的键。您在 &lt;li&gt; 标记中分配 key=4,因为元素 4 在您的数组中是重复的。

    编辑后

    我的错,我没有阅读完整的问题。 使用 uuid 包生成新的 id:https://www.npmjs.com/package/uuid 他们也有文档。

    【讨论】:

    • 尊敬的先生,但您正在解释我自己的问题:P
    • @AnkitPandey 我已经编辑了我的答案。试试这个,让我知道这是否适合你。
    • 成功了。我一直在寻找没有软件包的解决方案。感谢分享这个解决方案:)
    【解决方案3】:

    这样做会添加一个唯一键以及自定义数据

    import React from 'react';
    import ReactDOM from 'react-dom';
    
    
    const Numbers = ['2', '4', '6', '8'];
    
    const NumbersList = (props) => (
       <ul>
          {
              props.Numbers.map (
                 (number, i) => <li key={i} custom={number}>{number * 2}</li>
              )
          }
        </ul>
    )
    ReactDOM.render(<NumbersList Numbers = {Numbers} />, document.getElementById('root') )
    

    key prop 应该是唯一的,所以我给出了 map 方法的返回值,自定义属性将是您要为所有元素设置的数组数据。

    【讨论】:

    • 谢谢!虽然代码在添加唯一键后正常工作,但也没有自定义数据。
    【解决方案4】:

    React 期望重复项(兄弟项)具有关键属性,以便它可以区分后续渲染中的项。这允许它在项目来、去和更改时优化元素图的呈现。

    key 应该是一个字符串,但 React 会为你强制转换一个数字。您的示例非常简单,数据包含一些唯一的项目值(例如数据库记录 id)更正常,以便可以支持重复属性但仍允许区分项目。在没有外部 id 属性的情况下,您可以决定添加一个唯一标识符作为状态的一部分。

    可以使用列表中的项目索引,但这并不总是允许 React 优化项目的渲染周期。这就是为什么如果您的数据包含唯一的项目标识符,它不鼓励。

    React 检查重复和丢失的键,以避免可能导致渲染周期效率降低的最明显错误。

    Reacts 渲染优化确实会对非常长的列表产生影响。对于范围可能只有几个项目的应用程序,不会有太大的收获,因此数组索引可能是一个合理的解决方案。

    【讨论】:

      【解决方案5】:

      index 用作key 是一种反模式,在任何情况下都会导致错误。

      为了获得最佳答案 - 如果有人将索引后面的数字 1 更改为 5 会发生什么?显示的数字将保持不变,因为key 没有更改

      为了绕过将index 用作基元的key 引起的问题,我建议使用复合键

      接下来我会写NumbersList 组件:

      const NumbersList = ({ numbers }) => ( <ul> {numbers.map((number, index) => ( <li key={`${index}:${number}`}>{number * 2}</li> )} </ul> );

      【讨论】:

      • 这是您的 NumbersList 组件变体的完全替代品。只需注意命名(小写的numbers prop)。我在这里使用了对象破坏,它允许跳过输入props 变量。
      【解决方案6】:

      恭喜,没有简单的答案。在映射字符串数组(最常见的情况)时,您不能确定它们是唯一的。所以你不能使用值作为键。

      您可以使用数组索引作为键。但是你不能因为它很糟糕,即使它是一个真正的静态数组。你不能,这很糟糕,eslint 这么说的。

      我建议编写一个简单的辅助函数。像这样:

      const mapArray = (source: string[]) => source.map((value, index) => ({id: index, value}))
      

      这也意味着你必须添加一个状态来存储这个地图,并在源发生变化时更新它。或者你可以写一个钩子,在 npm 上发布,让这个世界变得更美好。

      【讨论】:

        【解决方案7】:

        React 使用keys 来识别哪些元素已更改、添加或删除。

        选择key 的最佳方法是使用一个字符串,该字符串在其兄弟项中唯一标识一个列表项。大多数情况下,您会使用数据中的 ID 作为键。

        不建议使用数组索引作为键,因为您可以更新/删除数组中的元素,但索引将保持不变,因此 React 将无法识别更改并显示错误的结果。

        在您的代码中,您没有任何唯一的数组元素 id,因此唯一可以用来使其唯一的就是数组索引。

        const Numbers = ['2', '4', '4', '8'];
        
        const NumbersList = (props) => (
          <ul>
          {
          props.Numbers.map (
            (number, index) => <li key={index}>{number * 2}</li>
          )}
          </ul>
        )
        
        ReactDOM.render(
          <NumbersList Numbers = {Numbers} />,
          document.getElementById('root')
        )
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
        <div id="root"></div>

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-03-23
          • 2015-06-04
          • 2011-11-21
          • 1970-01-01
          • 2012-05-22
          相关资源
          最近更新 更多