【问题标题】:key prop warning in react with key and child components与关键和子组件反应的关键道具警告
【发布时间】:2020-06-23 03:15:55
【问题描述】:

据我所知,我在正确的组件上正确使用了key,但尽管我努力了,但错误仍然存​​在。

我有一个Notifications 组件,它通过array.map() 呈现单个Notification 组件的列表。通常,当通知的文本是字符串时,这可以正常工作,但是当它是 JSX(例如带有链接的p)时,我不断收到“子元素必须具有唯一键”警告。在这种情况下,只有一个通知,因此键 是唯一的。

这是在 Redux 中设置通知的代码:

props.setNotification({
  type: 'error',
  domain: 'page/section',
  text: (
    <p>
      An error occurred.{' '}
      <a href="/somewhere/else">Learn more</a>
    </p>
  )
})

通知组件读取 Redux 并循环访问相应的通知:

export const Notifications = ({ notifications, type, domain }) =>
  notifications
    .filter(
      note =>
        (!type && !domain) ||
        (domain && note.domain === domain) ||
        (type && note.type === type),
    )
    .map((note, i) => (
      <Notification key={`note_${i}`} note={note} />
    )

最后,单个通知组件只是基本的 JSX(这些组件是 StyledComponents):

const Notification = ({ className, note }) => (
  <Notification type={note.type} className={className}>
    <Icon name={typeIconMap[note.type]} size="18" />
    <Text>{note.text}</Text>
  </Notification>
)

警告说:

index.js:2178 Warning: Each child in a list should have a unique "key" prop. See docs for more information.
    in p
    in div (created by Text)
    in Text (created by Notifications)
    in div (created by Notification)
    in Notification (created by Notifications)
    in Notifications (at Notifications/index.js:15)
    in Notifications (created by Connect(Notifications))

到目前为止我已经尝试过:

  • setNotification 中创建的段落添加一个键,但它没有执行任何操作,尽管警告首先指向该元素。
  • 使用不同的元素代替 p,例如 React.Fragment,但这并没有改变,即使这些元素本身具有静态键。
  • key 传递到通知组件,但这会导致另一个错误,因为您无法在子项中传递/访问key
  • 将在Notifications 中分配的键更改为比{i} 更稳定的键。我尝试了{btoa(note.text)} 和其他一些变体,但没有任何效果。如果text 只是一个字符串,它甚至可以在直接使用单个Notification 时工作(手动给它一个note 对象而不是使用Notifications,即使使用JSX 作为text)我不明白为什么这种特定情况会引发错误。

我在这里有什么明显的遗漏吗?为什么当text 是纯字符串时这有效,而当它是 JSX 时则无效。

【问题讨论】:

  • 你使用 const 和 element 同名Notification ?

标签: javascript reactjs


【解决方案1】:

我通过使用 Math.random() 为密钥分配随机值来解决此警告 你可以这样尝试:

<Notification key={Math.random()} />

【讨论】:

  • 这是我尝试过的事情之一,但并没有改变它。这实际上是一种反模式,因为密钥不够静态,因此 React 无法正确验证组件是否需要重新渲染,因此无论如何都要这样做以确保安全,从而导致性能损失。
【解决方案2】:

如果您为 Notification 添加片段,并提供适当的 React 元素,它将按预期工作

const notificationList = [
  {
    type: "error",
    domain: "page/section",
    text: (
      <p>
        An error occurred. <a href="/somewhere/else">Learn more</a>
      </p>
    )
  }
];

const Notifications = ({ notifications, type, domain }) => (
  <>
    {notifications
      .filter(
        note =>
          (!type && !domain) ||
          (domain && note.domain === domain) ||
          (type && note.type === type)
      )
      .map((note, i) => (
        <Notification key={`note_${i}`} note={note} />
      ))}
  </>
);

const Text = props => <>{props.children}</>;
const Notification = ({ className, note }) => <Text>{note.text}</Text>;
const App = () => {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <Notifications
        notifications={notificationList}
        type="error"
        domain="page/section"
      />
    </div>
  );
}

【讨论】:

  • 感谢您的回答并提供 sn-ps。不幸的是,这仍然对我不起作用。第一个问题是&lt;&gt; &lt;/&gt; 触发了无效令牌警告并且无法正确编译。即使使用 React.Fragments,它仍然会抛出错误。我尝试让 Notification 只返回 note.text 甚至包含在片段中的内容,但仍然会引发错误,尽管错误堆栈略有不同。它只会让这个特定的问题更加令人困惑。
  • 您能否在某处复制问题以检查类似代码和框?
  • 什么是>如果它不是片段????
猜你喜欢
  • 2018-09-28
  • 2020-10-13
  • 2016-07-21
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
  • 2021-09-01
  • 2020-03-27
  • 2020-12-30
相关资源
最近更新 更多