Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

一篇文章告诉你React里为什么不能用index作为key #5

Open
z2014 opened this issue Sep 1, 2017 · 2 comments
Open

一篇文章告诉你React里为什么不能用index作为key #5

z2014 opened this issue Sep 1, 2017 · 2 comments

Comments

@z2014
Copy link
Owner

z2014 commented Sep 1, 2017

之前在写react的时候,当我们做map循环的时候,当我们没有一个唯一id来标识每一项item的时候,我们可能会选择使用index

data.map((item, index) => {
    return <li key={index}>{item}</li> 
})

但是其实当你使用index来作为唯一key的时候,其实是由一个大坑的,什么坑呢?必须坑了你才知道,来看下面的这种情况:

class App extends React.Component{
	constructor(props) {
		super(props)
		this.state = {
			list: [{id: 1,val: 'aa'}, {id: 2, val: 'bb'}, {id: 3, val: 'cc'}]
		}
	}

	click() {
		this.state.list.reverse()
		this.setState({})
	}
	splice() {
		this.state.list.splice(1,1)
		this.setState({})
	}

	render() {
		return (
            <ul>
                <div onClick={this.splice.bind(this)}>delete</div>
                <div onClick={this.click.bind(this)}>reverse</div>
                {
                	this.state.list.map(function(item, index) {
                		return (
                            <Li key={index} val={item.val}></Li>
                		)
                	}.bind(this))
                }
            </ul>
		)
	}
}

class Li extends React.Component{
	constructor(props) {
		super(props)
	}
	componentDidMount() {
		console.log('===mount===')
	}
	componentWillUpdate(nextProps, nextState) {
		console.log('===update====')
	}
	render() {
		return (
            <li>
                {this.props.val}
                <input type="text"></input>
            </li>
		)
	}
}

页面渲染好了之后,3个input输入框依次输入1,2,3:
当我们用index作为key的时候,点击reverse会发现,input输入框还是1,2,3顺序显示,但是这并不符合我们的预期,控制台中此时打印的也是update;
当我们用对象中的id作为key的时候,点击reverse,此时神奇的事情发生了,input输入框变成了3,2,1,符合我们的预期,控制台此时打印的也是update;

为什么会这样呢?

当我们传入index作为key时,此时的key为0,1,2,
当我们点击reverse重新排序后,index传进去的key还是0,1,2,此时react比较key=0时,发现只需要更新子节点的值就可以,于是只把item替换成了cc,而input则相反,
当我们传入id作为index的时候,,点击reverse后,此时的key变成了3,2,1,根据react的diff算法,react还是能分辨出只需要移动子节点即可完成更新,因此input也随之变化。

那说了这么多,其实对于index作为key我们是不推荐的,除非你能够保证他们不会发生变化。

参考文献
index as a key is an anti-pattern

@codezyc
Copy link

codezyc commented Oct 4, 2017

mark

@xiaobinwu
Copy link

mark

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants