避免必须为非常简单的元素列表指定键

Avoid having to specify a key for list of very simple elements

我正在开发一个使用 JSXReact 编写的应用程序,其中一些元素的内容不是很结构化,但仍然生成程序上。一个例子是将列表中的字符串放在单独的行上:

function getRow(items) {
     let elements = [];

     // Procedurally generate the list of elements.
     for (let i of items) {
          if (elements.length > 0) {
                // Add line breaks between the line.
                elements.push(<br />);
          }

          elements.push(i);
     }

     return <tr>
          {/* More elements here. */}
          <td>
                {/* Place the element into the cell. */}
                {elements}
          </td>
          {/* More elements here. */}
     </tr>;
}

其他示例是添加一些基于状态或上下文的样式,但元素从不嵌套或它们本身本质上是复杂的。问题在于,对于这段代码,React 会显示有关元素缺少 key 属性的警告。发生这种情况是因为元素作为列表放入 JSX 树中,而 React 正试图帮助我编写高效的代码。

Warning: Each child in an array or iterator should have a unique "key" prop. ...

当然我可以只将这些 key 属性添加到每个元素,但是当每个迭代项生成多个元素或者没有迭代索引作为键的基础时,它会变得非常麻烦。在我正在查看的情况下,添加这些键似乎没有好处。如果在这些情况下每次更改其中一个元素时仅替换所有元素实际上比基于 key 属性的 React 逻辑更快,我不会感到惊讶。

在这些情况下是否有一种干净的方法来禁用来自 React 的警告,或者是否有不同的方法将元素插入 JSX 树而不触发警告?

这可能无法回答 "how do I disable" 问题,但我建议一种方法来处理缺少密钥的问题而不是症状 :-P ..有以编程方式生成密钥的干净方法。尝试这样的事情:

function getRow(items) {
    const elements = [];
    items.map((item, index) => {
        elements.push(
          <tr key={'row-' + index}>
             <td>{item.value1}</td>
             <td>{item.value2}</td>
             <td>{item.value3}</td>
          </tr>
        );
    });
    return elements;
}

每当您返回项目数组时,您需要指定一个键,以便 React 可以区分它们,这并不难,因为每个 loop/map 都有唯一的索引或键字段,您可以将其用作键,你可以给它们加上前缀,这样同一个循环中的两个键也不会冲突

[1,2,3].forEach((item,index)=>{
  arr.push(<div key={`forEachloop-${i}`></div>)
  if(somecondition == true){
  /** prefix for making key unique **/
  arr.push(<div key={`forEachloop-condition-${i}`></div>)
  }
}

[1,2,3].map((item,index)=>{
  return (<div key={`forEachloop-${i}`></div>)
}

如果您真的在尝试构建elements绝对[=时不知道items中会有哪些组件23=] 创建组件时不能使用合理的键或添加基于索引的键,你可以使用它来删除警告:

function getRow(items) {
     let elements = [];

     // Procedurally generate the list of elements.
     for (let i of items) {
          if (elements.length > 0) {
                // Add line breaks between the line.
                elements.push(<br />);
          }

          elements.push(i);
     }

     // Ensure there is a unique key for all elements
     elements = elements.map((e, i) => React.cloneElement(e, { key: i }))

     return <tr>
          {/* More elements here. */}
          <td>
                {/* Place the element into the cell. */}
                {elements}
          </td>
          {/* More elements here. */}
     </tr>;
}

这应该只用作 绝对的最后手段 我不保证它的性能,因为它正在克隆每个元素以给它一个 key。它还将覆盖元素上已有的 key,因此在某些元素上使用合理的 key 的任何好处都将丢失。