ReactJS循环生成Card组件时,如何为onClick传递唯一key?
解决React循环生成Card时onClick传递错误key的问题
嘿,这个问题我之前也踩过坑!核心就是JavaScript里var和let的作用域差异在搞鬼,咱们一步步来解决:
问题根源
你用var循环生成Card时,所有的onClick回调共享同一个变量引用。因为var是函数级作用域,整个循环里只有一个key变量绑定。等用户点击卡片的时候,循环早就跑完了,key自然指向最后一个元素的属性名(比如你例子里的'c')。
最简单的解决方案:把var换成let
利用let的块级作用域,每次循环迭代都会创建一个新的key变量绑定,这样每个Card的onClick回调都会捕获当前迭代对应的key值,不会再串味。
错误写法(用var导致的问题)
const cardData = {'a':'A', 'b':'B', 'c':'C'}; function CardList() { const cards = []; // 用var的话,所有onClick共享同一个key引用 for (var key in cardData) { cards.push( <Card key={key} onClick={() => handleDelete(key)} // 点击任何卡片都会传递'c' > {cardData[key]} </Card> ); } return <div>{cards}</div>; }
正确写法(换成let)
const cardData = {'a':'A', 'b':'B', 'c':'C'}; function CardList() { const cards = []; // 用let,每次迭代创建独立的key绑定 for (let key in cardData) { cards.push( <Card key={key} onClick={() => handleDelete(key)} // 点击对应卡片传递正确的key > {cardData[key]} </Card> ); } return <div>{cards}</div>; }
更推荐的React写法:用map遍历
在React中,我们更常用数组的map方法来生成组件列表,这种方式天然避免了作用域问题,代码也更简洁:
const cardData = {'a':'A', 'b':'B', 'c':'C'}; function CardList() { return ( <div> {Object.entries(cardData).map(([key, value]) => ( <Card key={key} onClick={() => handleDelete(key)} // 每个map迭代的key都是独立的 > {value} </Card> ))} </div> ); }
补充说明
本质上,闭包会捕获变量的引用而非值。用
var时,所有回调捕获的是同一个key变量的引用;用let时,每次循环都会生成一个新的key变量,每个回调捕获的是当前迭代的变量引用,自然就能拿到正确的值啦。
内容的提问来源于stack exchange,提问作者Abhiram Natarajan
相关产品推荐
相关产品推荐

