【问题标题】:React - Warning: Each child in a list should have a unique "key" propReact - 警告:列表中的每个孩子都应该有一个唯一的“关键”道具
【发布时间】:2020-03-01 05:12:44
【问题描述】:

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

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

在我看来,我把密钥放在了正确的位置,形式为 key={item.login.uuid}

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

App.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


    【解决方案1】:

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

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

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

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

    请注意,您的示例中实际上不需要该片段,您可以删除它并将keys 保留在它们所在的位置,此后&lt;div&gt;&lt;li&gt; 将成为根元素:

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

    【讨论】:

      【解决方案2】:

      如果您创建 2 个单独的组件,一个用于用户视图,一个用于列表项,该怎么办。这样你只需要传递用户道具。另外,使用 JSX 并从那里传递 wht 键。

      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 User = ({user}) => (
          <div key={user.login.uuid}>
            <div>
              <h2>
                {user.name.first} {user.name.last}
              </h2>
              <p>
                {user.phone}
                <br />
                {user.email}
              </p>
              <button onClick={() => setID(null)}>
                Back to the list
              </button>
            </div>
          </div>
        )
      
        const ListItem = ({user}) => (
          <li key={user.login.uuid}>
            <div>
              <h2>
                {user.name.first} {user.name.last}
              </h2>
              <button onClick={() => setID(user.login.uuid)}>
                Details
              </button>
            </div>
          </li>
        )
      
        const user = resources.find(user => user.login.uuid === id)
      
        if (user) {
          // User view
          return <User user={user}</div>
        } else {
          // List view
          return (
            <ul>
              {resources.map((user, index) => <ListItem key={index} user={user} />)}
            </ul>
          )
        }
      }
      
      export default UserList
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-04
        • 2021-01-12
        • 2022-06-28
        • 1970-01-01
        • 2021-11-18
        • 1970-01-01
        • 2023-02-17
        • 2019-12-05
        相关资源
        最近更新 更多