【问题标题】:Why am I receiving this Warning: Each child in a list should have a unique "key" prop为什么我会收到此警告:列表中的每个孩子都应该有一个唯一的“关键”道具
【发布时间】:2021-11-29 19:20:49
【问题描述】:

我将索引作为唯一键传递,但我仍然收到此警告:

警告:列表中的每个孩子都应该有一个唯一的“key”属性。

查看SectionPackages的渲染方法

谁能指导我可能是什么问题?

const SectionPackages = props => {

  const listingPackages =
    publicData && publicData.packages && publicData.packages.length
      ? [defaultPackage, ...publicData.packages]
      : [];

  useEffect(() => {
    listingPackages.map((l, index) => {
      hidden[index] = true;
      setHidden([...hidden]);
    });
  }, []);

  return (
    <div className={listingPackages.length ? rootClassName : css.noPackages}>
      {listingPackages.length > 0 && (
        <h2 className={css.packagesMainTitle}>
          <FormattedMessage id="SectionPackages.title" />
        </h2>
      )}

      {listingPackages.map((listingPackage, index) => {
        const moneyPrice = new Money(
          listingPackage.price.amount * 100,
          listingPackage.price.currency
        );

        return (
          <a onClick={e => handleBtnClick(e, index)} key={index}>
            <div
              key={index}
              className={
                selectedPackage === index && selectedPackage !== null
                  ? classNames(css.packagesContainer, css.packagesSelectedContainer)
                  : css.packagesContainer
              }
            >

              <div className={css.packagesDescriptionHolder}>
                {listingPackage.description != null && (
                  <p
                    className={
                      hidden[index] === true
                        ? classNames(css.packagesDescriptionHidden, 'packagesDescription')
                        : classNames(css.packagesDescriptionShown, 'packagesDescription')
                    }
                  >
                    {listingPackage.description}
                  </p>
                )}
                {elHeight[index] && elHeight[index].index === index && elHeight[index].height > 40 && (
                  <p
                    className={css.packagesDescriptionMore}
                    onClick={e => showHideDescription(e, index)}
                  >
                    {hidden[index] === true ? (
                      <FormattedMessage id="SectionPackages.showMore" />
                    ) : (
                      <FormattedMessage id="SectionPackages.showLess" />
                    )}
                  </p>
                )}
              </div>
            </div>
          </a>
        );
      })}
    </div>
  );
};

【问题讨论】:

  • 我没有看到此代码有任何直接问题,React 键使用的是映射数组索引,因此它不能重复。你是否在这个 React 组件子树中的任何其他地方映射了任何东西?您能否将完整的错误消息和堆栈跟踪(如果有)添加到您的问题中?
  • @DrewReese 已添加,请查看
  • 谢谢,仍然不清楚在哪里可能出现重复键。认为您可以为该组件创建一个 running 代码和框,其中包含模拟数据/道具,以重现我们可以实时检查和调试的关键问题?

标签: reactjs


【解决方案1】:

当你使用 map 或任何其他循环函数时,你需要为你在 react 中生成的每个元素分配一个唯一的键。

在您的情况下,您将索引分配给同一循环中的“a”标签和“div”。

您可以通过添加某种前缀来使它们独一无二,例如:

     <a onClick={e => handleBtnClick(e, index)} key={`a_${index}`}>
        <div
          key={`div_${index}`}

这样,a 的键与 div 的键不同。

作为替代解决方案,您可以从 div 中删除“key”并将其保留在“a”标签上。

注意事项 我想澄清一下,因为它的工作原理似乎有些混乱。

在这种情况下,相同的键被用于“a”和“div”,它们都在相同的循环中.

在这种情况下 "a",您需要将键分配给 map 函数返回的根元素。

React 将使用 key 将之前的虚拟 dom 与当前的虚拟 dom 进行比较并执行合并。这与“识别”元素中的元素无关。

此外,不建议使用“index”作为键,因为索引可能会在下一次传递时出现在不同的项目上。

这是来自 react 文档的引用:

如果项目的顺序可能发生变化,我们不建议对键使用索引。这会对性能产生负面影响,并可能导致组件状态出现问题。

https://reactjs.org/docs/lists-and-keys.html

同时检查Index As Key Anti-Pattern

【讨论】:

  • 这是一个很棒的评论。不是一个很好的答案,因为它实际上只是说明了显而易见的事情。此外,键只需要在兄弟姐妹之间是唯一的,而不是孩子,因此嵌套的 div 可以使用相同的 React 键。
  • @DrewReese 不是真的我不同意你的看法。他在同一个循环中对两个不同的对象使用相同的密钥并不明显。在这种情况下也是正确的答案。
  • 根据定义,数组索引对于所有元素总是是唯一的。没有办法在数组中有重复的索引。你不必同意我的观点,但这个答案是不正确的。这是React keys and usage 的复习,请关闭注意关于兄弟姐妹之间的独特性的第二部分。跨度>
  • 它不是唯一的,因为您为“a”和“div”分配了相同的键......要求不是“在父级内”是在“元素的父级”内在循环”。 @LaveenRen
  • @LaveenRen 换句话说,您需要使 div 键不同或将其删除。需要的一个键是“a”标签键,它是 map 函数返回的根元素。
猜你喜欢
  • 1970-01-01
  • 2019-08-04
  • 2021-01-12
  • 2022-06-28
  • 2023-02-17
  • 2019-12-05
  • 2021-09-05
  • 2020-03-01
  • 1970-01-01
相关资源
最近更新 更多