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

Reactjs 避免为非常简单的元素列表指定键,reactjs,react-jsx,Reactjs,React Jsx,我正在开发一个使用JSX编写的应用程序,其中一些元素的内容不是很结构化,但仍按程序生成。例如,可以将列表中的字符串放在单独的行上: function getRow(items) { let elements = []; // Procedurally generate the list of elements. for (let i of items) { if (elements.length > 0) {

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

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基于关键属性的逻辑更快,我也不会感到惊讶


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

这可能无法回答“如何禁用”问题,但是我建议用一种方法来解决缺少密钥的问题,而不是症状:-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能够区分它们,这并不困难,因为在每个循环/映射中都有唯一的索引或键字段,可以将其用作键,您可以为它们添加前缀,以便同一循环中的两个键也不会被确认

[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>)
}
如果您在尝试构建元素时确实不知道项中将包含哪些组件,并且在创建组件时绝对不能使用合理的键或添加基于索引的键,则可以使用此选项删除警告:

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

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

对于每个“元素”,您只需要根上的键,因此它不应该那么“麻烦”:共享从项生成元素的代码!正如Michael所说,这绝对是万不得已的手段。它可能会产生意想不到的副作用,并导致难以追溯到的问题。谢谢你的回答!按预期工作。我必须添加一个复选框才能将React.cloneElement仅应用于非字符串。否不是“我该怎么做…”类型问题的答案,即使我没有这样表达:PYou是对的@Feuermurmel,所以我重新措辞了我的答案。它仍然没有回答如何禁用警告,但是它解决了您对密钥的挑战。因此,禁用警告应该不再必要:-在这方面,它确实回答了您的问题是否有其他方法将元素插入JSX树而不会触发警告?
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>;
}