在回答this question时,我最终在以下代码中将索引用作键:
const menuItems = [
{ Page: ActiveDeals, Icon: Home },
{ Page: UpcomingDates, Icon: CalendarToday },
{ Page: DealsPipeline, Icon: FilterList }
];
const mappedMenuItems = menuItems.map((menuItem, index) => (
<DashboardListItem
key={index}
{...menuItem}
ShownPage={this.state.shownPage}
setShownPage={this.setShownPage}
/>
));
在这种情况下,这很好,因为顺序不是可变的,但是理想情况下,我应该使用特定于数据的唯一键。在这种情况下,我在数据中没有(或不需要)任何字符串标识符。关于此数组中每个条目的主要独特之处在于,内容成分是通过Page
属性传递给每个menuItem
的。该功能对于每个菜单项都是唯一的,并且随着时间的推移将保持稳定(不会随着重新渲染而改变),因此在呈现组件列表/数组时,它符合key
属性的大多数标准,但是该文档表示字符串为首选键类型。
所以我想知道,“将函数用作键可以吗?”
我在发布问题的同时提供了我自己的答案,但是如果您要添加一些内容,也可以随时回答-特别是在您知道React团队为何建议将字符串作为键的特定原因时
答案 0 :(得分:1)
要回答这个问题,我首先查看了文档,该文档肯定强烈建议键为字符串。
来自https://reactjs.org/docs/lists-and-keys.html#basic-list-component
“键”是特殊的字符串属性,您需要在添加该属性时 创建元素列表。
以及https://reactjs.org/docs/lists-and-keys.html#keys
选择键的最佳方法是使用唯一标识的字符串 兄弟姐妹中的一个列表项。当您没有稳定的ID时 呈现的项目,您可以将项目索引用作最后的选择键
到目前为止,文档中提到了字符串和整数(例如索引),但我仍然想知道使用其他内容是否有任何危害。因此,下一个要看的地方是源代码。
要找到正确的源代码,我在应该保留一个键的地方留下了一个键,然后使用生成的消息(“列表中的每个孩子都应该有一个唯一的...”)搜索GitHub存储库。这将我带到ReactChildFiber.js。然后,我发现了与我的问题相关的以下函数:
function mapRemainingChildren(
returnFiber: Fiber,
currentFirstChild: Fiber,
): Map<string | number, Fiber> {
// Add the remaining children to a temporary map so that we can find them by
// keys quickly. Implicit (null) keys get added to this set with their index
// instead.
const existingChildren: Map<string | number, Fiber> = new Map();
let existingChild = currentFirstChild;
while (existingChild !== null) {
if (existingChild.key !== null) {
existingChildren.set(existingChild.key, existingChild);
} else {
existingChildren.set(existingChild.index, existingChild);
}
existingChild = existingChild.sibling;
}
return existingChildren;
}
因此,这里的existingChildren
是用于密钥的Map
。Map可以支持作为密钥的功能,我尝试使用menuItem.Page
作为密钥,似乎可以正常工作,但是代码中的类型清楚地将string | number
指示为密钥的类型。
目前,我的结论是,应避免使用string | number
以外的其他类型,因为消息源将其声明为限制,并且可能由于某些原因,我不知道(可能与将来的计划有关)可能会使此限制更多比目前看来还重要,但是我仍然好奇是否有更充分的理由来限制用于键的类型。