使用唯一,稳定的函数(例如组件)而不是使用字符串作为React键可以吗?

时间:2019-02-07 23:35:27

标签: reactjs

在回答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团队为何建议将字符串作为键的特定原因时

1 个答案:

答案 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是用于密钥的MapMap可以支持作为密钥的功能,我尝试使用menuItem.Page作为密钥,似乎可以正常工作,但是代码中的类型清楚地将string | number指示为密钥的类型。

目前,我的结论是,应避免使用string | number以外的其他类型,因为消息源将其声明为限制,并且可能由于某些原因,我不知道(可能与将来的计划有关)可能会使此限制更多比目前看来还重要,但是我仍然好奇是否有更充分的理由来限制用于键的类型。