使用数组的索引作为KEY会导致不良后果
每个应用程序都会以这样或那样的方式使用列表/数组。在React中使用列表时,需要更加谨慎,因为key prop,它被用于数组中的元素。
key prop是DOM中一个元素的标识。所以,它应该是唯一的和静态的,以便区分不同的元素。如果你没有传递 prop,你最终会在控制台看到这个。key
Warning: Each child in a list should have a unique key prop
在这一点上,如果你认为,hey, it's just a warning... ,你在冒险**(请不要**)。因为这可能看起来不会造成严重的问题,相信我,你也不安全。
实现键的方法
用列表实现键有多种方法。
1.数组的索引
索引作为一个键是一种反模式的做法。这可能是摆脱控制台警告的最简单的方法,但这是一把双刃剑。如果没有适当的知识,这种方法可能会出错。
所以,让我们来看看在哪些情况下
-
索引不能作为键使用
- 如果新的元素被添加到开头或中间的某个地方
- 如果数组被过滤了
const App = () => { const [counter, setCounter] = useState(1); const [list, setList] = useState([ { id: counter, }, ]); const addToStart = () => { const newId = counter + 1; setCounter(newId); setList((oldArray) => [ { id: newId, }, ...oldArray, ]); }; const addToEnd = () => { const newId = counter + 1; setCounter(newId); setList((oldArray) => [ ...oldArray, { id: newId, }, ]); }; return ( <div className="App"> <button onClick={addToStart}>Add To Start</button> <button onClick={addToEnd}>Add To End</button> <table> <tr> <th>Id</th> <th>Item</th> </tr> {list.map((item, index) => ( <tr key={index}> <td> <label>{item.id}</label> </td> <td> <input /> </td> </tr> ))} </table> </div> ); };
在上面的代码片段中,我们有一个数组,我们可以在数组的开始/结束处添加元素。如果我们把元素添加到数组的末尾,Item 1 将有键0 ,Item 2 将有键1 。然后,如果元素被添加到数组的开始,Item 3 落在上面,但它最终的键是0 而不是2 。
为了避免这种意外的行为,我们不应该使用数组索引作为键:
{
list.map((item) => (
<tr key={item.id}>
<td>
<label>{item.id}</label>
</td>
<td>
<input />
</td>
</tr>
));
}
现在,如果按照上面同样的步骤,如果元素被添加到数组的开始,Item 3 落在上面,并且会有键值2
-
索引可以作为键使用
- 如果新的元素被推到数组的末端(因为将元素推到数组的末端不会影响现有元素的索引)。
- 如果该数组是静态的
- 如果数组没有被过滤
在上面的片段中,如果我们只在数组的末端添加元素,我们可以把数组的索引作为键。
{ list.map((item, index) => ( <tr key={index}> <td> <label>{item.id}</label> </td> <td> <input /> </td> </tr> )); }
这里是资源库的链接,其中,index 被用作key ,反之则用于转换。这个演示显示了使用索引作为键会导致意外的行为。
2.来自数据集的唯一ID
这无疑是最好的方法,因为你可以从提供的数据中获得唯一的ID:
const items = [
{
id: 1,
value: 'Item 1',
},
{
id: 2,
value: 'Item 2',
},
{
id: 3,
value: 'Item 3',
},
];
<div>
{items.map((item) => {
return <div key={item.id}>{item.value}</div>;
})}
</div>;
3.使用包生成唯一的ID
在你没有与列表一起的唯一ID的情况下,最好是在一些包的帮助下生成唯一的键。互联网上有很多软件包可用于生成唯一的键/ID,如react-uuid、uuid。我现在要用react-uuid:
import uuid from 'react-uuid';
const arrayWithoutIds = ['user 1', 'user 2', 'user 3'];
const arrayWithIds = arrayWithoutIds.map((element) => {
return {
id: uuid(),
value: element,
};
});
const Component = ({ arrayWithIds }) => {
return (
<div>
{arrayWithIds.map((item) => {
return <div key={item.id}>{item.value}</div>;
})}
</div>
);
};
这里需要记住的一点是,键应该在创建数据集时或在组件挂载前生成(componentWillMount ),以防止在每次渲染时生成唯一的ID。
4.Math.Random()
不建议使用Math.Random() ,因为它不稳定。因为,我们不能否认有可能产生两次相同的数字。
总结
- 尝试使用
unique id from dataset/generate unique ids using packages方法来实现密钥。 index作为钥匙可以作为最后的手段来使用。- 不要使用
Math.Random()作为键。
学习愉快