错误:不要在键中使用Array索引

Tan*_*tel 16 npm reactjs

我正在使用索引在列表中生成密钥.但是,es-lint会为此生成错误.React doc还指出,使用项索引作为键应该用作最后的手段.

const list = children.map((child, index) =>
    <li key={index}> {child} </li>);
Run Code Online (Sandbox Code Playgroud)

我考虑过使用react-key-index. npm install react-key-index给出以下错误:

npm ERR! code E404

npm ERR! 404 Not Found: react-key-index@latest

是否有其他包允许生成唯一密钥的建议?任何有关反应键生成器的建议都表示赞赏!

Rac*_*las 29

key={index}每当修改列表时,就会出现使用问题。React 不知道哪个项目被添加/删除/重新排序,因为索引是根据数组中项目的顺序在每个渲染上给出的。虽然,通常它呈现得很好,但仍然存在失败的情况。

这是我在构建带有输入标签的列表时遇到的示例。一个列表基于索引呈现,另一个基于 id 呈现。每次在输入中键入任何内容然后删除项目时,都会出现第一个列表的问题。在重新渲染时,React 仍然显示好像该项目仍然存在。这是很难发现和调试的 UI 问题。

在此处输入图片说明

    class List extends React.Component {
      constructor() {
        super();
        this.state = {
          listForIndex: [{id: 1},{id: 2}],
          listForId: [{id: 1},{id: 2}]
        }
      }
      renderListByIndex = list => {
        return list.map((item, index) => {
          const { id } = item;
          return (
              <div key={index}>
                <input defaultValue={`Item ${id}`} />
                <button 
                  style={{margin: '5px'}} 
                  onClick={() => this.setState({ listForIndex: list.filter(i => i.id !== id) })}
                 >Remove</button>
              </div>
          )
        })
      }
      renderListById = list => {
        return list.map((item) => {
          const { id } = item;
          return (
              <div key={id}>
                <input defaultValue={`Item ${id}`} />
                <button 
                  style={{margin: '5px'}} 
                  onClick={() => this.setState({ listForId: list.filter(i => i.id !== id) })}
                 >Remove</button>
              </div>
          )
        })
      }
      render() {
        const { listForIndex, listForId } = this.state;
        return (
          <div className='flex-col'>
            <div>
              <strong>key is index</strong>
              {this.renderListByIndex(listForIndex)}
            </div>
            <div>
              <strong>key is id</strong>
              {this.renderListById(listForId)}
            </div>
          </div>
        )
      }
    }

    ReactDOM.render(
      <List />,
      document.getElementById('root')
    );
Run Code Online (Sandbox Code Playgroud)
.flex-col {
  display: flex;
  flex-direction: row;
}

.flex-col > div {
  flex-basis: 50%;
  margin: .5em;
  padding: .5em;
  border: 1px solid #ccc;
 }
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <div id="root">
        <!-- This element's contents will be replaced with your component. -->
    </div>
Run Code Online (Sandbox Code Playgroud)

  • 有那么一瞬间我以为我的光标在自己移动 (2认同)

pal*_*alm 25

当您使用数组的索引作为键时,React将优化并且不按预期呈现.在这种情况下发生的事情可以用一个例子来解释.

假设父组件获取10个项目的数组,并根据该数组呈现10个组件.假设然后从数组中删除第5项.在下一个渲染中,父级将接收9个项目的数组,因此React将渲染9个组件.这将显示为第10个组件被删除,而不是第5个,因为React无法区分基于索引的项目.

因此,始终使用唯一标识符作为从项目数组呈现的组件的键.

您可以使用唯一作为键的子对象的任何字段来生成您自己的唯一键.正常情况下,如果可用,可以使用子对象的任何id字段.

编辑:如果组件创建和管理自己的状态,例如在不受控制的文本框,计时器等中,您将只能看到上述行为.例如,删除输入组件时出现React错误

  • 我没有关注这个例子 - 你能提供一个重现这个问题的工作例子吗?我经常使用数组,从来没有遇到过这类问题. (2认同)

Dar*_*iya 11

当然,在React中,您需要为数组的所有元素传递唯一的键值。否则,您将在控制台中看到此警告。

\n
\n

警告:数组或迭代器中的每个子项都应具有唯一的 \xe2\x80\x9ckey\xe2\x80\x9d 属性。

\n
\n

所以,作为一个懒惰的开发者,你只需传入loop\xe2\x80\x99s索引值作为子元素的键值即可。

\n

当索引用作键时,对列表重新排序,或者从列表中添加和删除项目可能会导致组件状态出现问题。如果键是索引,则对项目重新排序会更改它。因此,组件状态可能会混淆,并且可能将旧密钥用于不同的组件实例。

\n

使用索引作为键是安全的,有哪些例外情况?

\n
    \n
  • 如果您的列表是静态的并且不会改变。
  • \n
  • 该列表永远不会重新排序。
  • \n
  • 该列表不会被过滤(从列表中添加/删除项目)。
  • \n
  • 列表中的项目没有 ID。
  • \n
\n

Key 应该是唯一的,但仅限于其兄弟姐妹中。

\n