首页 > 解决方案 > React - 警告:列表中的每个孩子都应该有一个唯一的“关键”道具

问题描述

在这个简单的 React App 中,我不明白为什么会收到以下警告消息:

警告:列表中的每个孩子都应该有一个唯一的“关键”道具。

对我来说,我似乎把钥匙放在了正确的地方,形式为key={item.login.uuid}

我怎样才能摆脱警告信息?把钥匙放在哪里合适?

应用程序.js

import UserList from './List'

const App = props => {
  const [id, newID] = useState(null)
  return (
    <>
      <UserList id={id} setID={newID} />
    </>
  )
}

export default App

List.js

const UserList = ({ id, setID }) => {
  const [resources, setResources] = useState([])

  const fetchResource = async () => {
    const response = await axios.get(
      'https://api.randomuser.me'
    )
    setResources(response.data.results)
  }

  useEffect(() => {
    fetchResource()
  }, [])

  const renderItem = (item, newID) => {

    return (
      <>
        {newID ? (
          // User view
          <div key={item.login.uuid}>
            <div>
              <h2>
                {item.name.first} {item.name.last}
              </h2>
              <p>
                {item.phone}
                <br />
                {item.email}
              </p>
              <button onClick={() => setID(null)}>
                Back to the list
              </button>
            </div>
          </div>
        ) : (
          // List view
          <li key={item.login.uuid}>
            <div>
              <h2>
                {item.name.first} {item.name.last}
              </h2>
              <button onClick={() => setID(item.login.uuid)}>
                Details
              </button>
            </div>
          </li>
        )}
      </>
    )
  }

  const user = resources.find(user => user.login.uuid === id)

  if (user) {
    // User view
    return <div>{renderItem(user, true)}</div>
  } else {
    // List view
    return (
      <ul>
        {resources.map(user => renderItem(user, false))}
      </ul>
    )
  }
}

export default UserList

标签: reactjs

解决方案


key需要位于循环内的根级元素上。在您的情况下,这就是片段(<>)。

为了能够做到这一点,您需要完整地写出来:

const renderItem = (item, newID) => {

  return (
    <Fragment key={item.login.uuid}>
      {newID ? (
        ...
      )}
    </Fragment>
  );
}

(您可以添加Fragment到来自 的其他导入react)。

请注意,您的示例中实际上并不需要该片段,您可以删除它并将keys 保留在它们所在的位置,从那时起<div>and<li>将成为根元素:

const renderItem = (item, newId) => {

  return newID ? (
    <div key={item.login.uuid}>
      ...
    </div>
  ) : (
    <li  key={item.login.uuid}>
      ...
    </li>
  )
}

推荐阅读