首页 > 解决方案 > 使用独特的、稳定的函数(例如组件)而不是字符串作为 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 团队推荐字符串作为键的具体原因。

标签: reactjs

解决方案


为了回答这个问题,我首先查看了强烈建议键是字符串的文档。

来自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;
  }

所以这里existingChildrenMap使用keys的地方。map可以支持函数作为keys,我尝试使用menuItem.Pageas my key,看起来效果很好,但是代码中的类型清楚地表明string | number了key的类型。

现在我的结论是string | number应该避免使用其他类型,因为消息来源声明这是一个限制,并且可能有我不知道的原因(可能关于未来的计划)可能使这个限制比现在看起来更重要,但我仍然很好奇是否有更强有力的理由来限制用于键的类型。


推荐阅读