reactjs - 使用独特的、稳定的函数(例如组件)而不是字符串作为 React 键是否可以?
问题描述
在回答这个问题时,我最终在以下代码中使用了索引作为键:
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
属性传递给 each的内容组件menuItem
。此功能对于每个菜单项都是唯一的,并且会随着时间的推移保持稳定(不会随着重新渲染而改变),因此它key
在渲染组件列表/数组时符合大多数属性标准,但文档表明字符串是首选键类型。
所以我想,“使用函数作为键可以吗?”
我在发布问题的同时包含了我自己的答案,但如果你有什么要补充的,也可以随时回答——特别是如果你知道 React 团队推荐字符串作为键的具体原因。
解决方案
为了回答这个问题,我首先查看了强烈建议键是字符串的文档。
来自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
使用keys的地方。map可以支持函数作为keys,我尝试使用menuItem.Page
as my key,看起来效果很好,但是代码中的类型清楚地表明string | number
了key的类型。
现在我的结论是string | number
应该避免使用其他类型,因为消息来源声明这是一个限制,并且可能有我不知道的原因(可能关于未来的计划)可能使这个限制比现在看起来更重要,但我仍然很好奇是否有更强有力的理由来限制用于键的类型。
推荐阅读
- python - 列表中的项目也是列表,我想让它们成为字符串 - Python
- javascript - 每 5 秒对特定数字重复一次操作,并且必须检查整个数组
- r - dplyr:是否可以使用一个函数在汇总中返回两列?
- git - 我在 GitHub 的拉取请求期间遇到问题
- python - Python二等分搜索混淆
- rust - 理解 Rust 中的引用生命周期
- jmeter - Jmeter线程组中可以使用的全局递增字段
- sql - 优化sql中的子查询
- javascript - script.js:24 Uncaught (in promise) ReferenceError: att is not defined
- mysql - MySQL Total Friends 找到多个最大值(如果存在)