react中什么情况下不能用index作为key

简介: react中什么情况下不能用index作为key

立志用功如种树然,方其根芽,犹未有干;及其有干,尚未有枝;枝而后叶,叶而后花。——王守仁

我们在React遍历渲染列表时会遇到这样一个报错:

意思是说,渲染list列表时必须给每个元素指定一个唯一的key

当然你可以选择忽略这个报错,但是为什么会提示这个报错呢?

假设我们给key指定一个随机数,或者干脆不指定的话,会怎么样呢?

官方文档给出了答案:

渲染列表时的逻辑以及问题

为了解决上述问题,React 引入了 key 属性。

也就是说,如果给key指定一个随机数,或者干脆不指定的话,会造成性能问题

这个时候,我们想到了用遍历时的元素下标作为key

但是官方文档明确告诉我们:

如果列表项目的顺序可能会变化,我们不建议使用索引来用作 key 值,因为这样做会导致性能变差,还可能引起组件状态的问题。可以看看 Robin Pokorny 的深度解析使用索引作为 key 的负面影响这一篇文章。如果你选择不指定显式的 key 值,那么 React 将默认使用索引用作为列表项目的 key 值。

这里Robin Pokirny的文章中提到了,如果满足这三者,可以放心使用index作为key

  • 列表和项目是静态的——它们不会被计算,也不会改变
  • 列表中的项目没有ID
  • 列表永远不会被重新排序或过滤

我精简了文章Demo中的了代码,代码如下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>index-as-a-key-is-an-anti-pattern</title>
  </head>
  <body>
    <!-- We will put our React component inside this div. -->
    <div id="root"></div>
    <!-- Load React. -->
    <!-- Note: when deploying, replace "development.js" with "production.min.js". -->
    <script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <!-- Load our React component. --> 
    <script src="index.js" type="text/babel"></script>
  </body>
</html>


index.js

class Item extends React.Component {
    render() {
        return (
            <div className="form-group">
                <label>{this.props.name}</label>
                <input type="text" />
            </div>
        )
    }
}
class Example extends React.Component {
    constructor() {
        super();
        this.state = {
            list: [
                { name: '原来有的: 1444610101010', id: 1444610101010 },
                { name: '原来有的: 1444600000000', id: 1444600000000 }
            ]
        };
    }
    addItem() {
        const id = +new Date;
        this.setState(state => ({ list: [{ name: '新增的' + id, id }, ...state.list] }));
    }
    render() {
        return (
            <div>
                <button className='btn btn-primary' onClick={this.addItem.bind(this)}><b>Add item</b> to the beginning of the list</button>
                <h3>Dangerous <code>key=index</code></h3>
                <form>
                    {this.state.list.map((todo, index) =>
                        <Item {...todo}
                            key={index}
                             />
                    )}
                </form>
                <h3>Better <code>key=id</code></h3>
                <form>
                    {this.state.list.map((todo) =>
                        <Item {...todo}
                            key={todo.id} />
                    )}
                </form>
            </div>
        )
    }
}
ReactDOM.render(<Example />, document.querySelector('#root'))

这里效果如下:

两个list中,第一个是使用index作为key的,第二个是用的id作为key

我们在文本框随便写点什么

此时我们点击按钮,新增一行,神奇的事情发生了

我们可以看到第一个list出现了错误,我们新增的一行文本框中竟然包含了原来有的文本框的值,并且列表中下方其他的文本框也错乱了

而我们使用id作为key的就没有出现这种问题。。。因此,我们在不满足上面说的三种条件时,在react中尽量不要使用元素下标作为key

相关文章
|
1月前
|
JavaScript 前端开发 算法
写 React / Vue 项目时为什么要在列表组件中写 key
在React或Vue项目中,为列表组件中的每个元素添加唯一的key属性,有助于框架高效地更新和渲染列表。Key帮助虚拟DOM识别哪些项已更改、添加或删除,从而优化性能并减少不必要的重新渲染。
|
5月前
|
前端开发 索引
解决React报错Encountered two children with the same key
解决React报错Encountered two children with the same key
|
前端开发 JavaScript
react 数组下标来作为 react组件中的key
react 数组下标来作为 react组件中的key
116 0
|
6月前
|
前端开发 JavaScript 数据库
React一般可以用哪些值作为key?
React一般可以用哪些值作为key?
|
6月前
|
JavaScript 前端开发 算法
说说React中的虚拟dom?在虚拟dom计算的时候diff和key之间有什么关系?
说说React中的虚拟dom?在虚拟dom计算的时候diff和key之间有什么关系?
44 0
|
6月前
|
前端开发 算法 JavaScript
React中的key有什么作用?
React中的key有什么作用?
69 0
|
6月前
|
JavaScript 前端开发 算法
说说react中虚拟DOM 在虚拟DOM中diff和key之间有什么关系
说说react中虚拟DOM 在虚拟DOM中diff和key之间有什么关系
52 0
|
前端开发 JavaScript 算法
React循环DOM时为什么需要添加key
React循环DOM时为什么需要添加key
|
前端开发
【React工作记录五十九】根据key值过滤形成新得数组
【React工作记录五十九】根据key值过滤形成新得数组
81 0
|
前端开发
react学习案例8-virtual-dom和key的作用
react学习案例8-virtual-dom和key的作用
73 0
react学习案例8-virtual-dom和key的作用