React前端渲染列表时出现Key属性警告问题求助
React列表渲染key警告问题排查与解决
问题描述
我在使用ReactJS渲染列表时出现如下警告:
react-jsx-dev-runtime.development.js:87 Warning: Each child in a list should have a unique "key" prop. Check the render method of `DriverList`. See https://reactjs.org/link/warning-keys for more information. at DriverList (http://localhost:3000/static/js/bundle.js:720:13) at div at Drivers (http://localhost:3000/static/js/bundle.js:1401:75) at Routes (http://localhost:3000/static/js/bundle.js:47364:5) at Router (http://localhost:3000/static/js/bundle.js:47297:15) at BrowserRouter (http://localhost:3000/static/js/bundle.js:46106:5) at App
我尝试了多种方式添加key属性来解决,但均未成功:给Driver组件添加key、给包裹Driver的React Fragment添加key、添加额外外层div并设置key、给Driver组件内的li元素添加key,单独或组合尝试这些方法后,警告依然存在,希望有人能指出我代码中的问题。
以下是DriverList组件的代码:
import React from "react" import Driver from "./Driver" import Card from "../../shared/components/interface/Card" import "./DriverList.css" const DriverList = (props) => { if (props.items.length === 0) { return ( <Card key='none'> <h2>No drivers found.</h2> </Card> ) } else { // Render the List return ( <ul className='driver-list'> {props.items.map((driver) => { return ( <React.Fragment key={driver.id}> <Driver key={driver.id} id={driver.id} permitno={driver.permitno} fname={driver.fname} lname={driver.lname} mailaddr1={driver.mailaddr1} mailaddr2={driver.mailaddr2} dateofbirth={driver.dateofbirth} driversex={driver.driversex} licenseidno={driver.licenseidno} dvrclass={driver.dvrclass} dvrpermit={driver.dvrpermit} endorsemnt={driver.endorsemnt} restricts={driver.restricts} expdate={driver.expdate} cmpldate={driver.cmpldate} numpoints={driver.numpoints} suspended={driver.suspended} driver_status={driver.driver_status} /> </React.Fragment> ) })} </ul> ) } } export default DriverList
问题排查与解决
问题出在列表的直接子元素上:你用<React.Fragment>包裹了Driver组件,但如果Driver组件内部渲染的是<li>元素,那么<ul>下实际的子元素是多个<li>,而这些<li>并没有拿到正确的key——你把key加在了外层的Fragment和Driver组件上,但React要求key必须绑定在列表循环产生的、直接作为<ul>子元素的节点上。
另外,当Fragment只包裹单个元素时,这个Fragment完全是多余的,可以直接移除。修改方案分两种情况:
情况1:Driver组件根元素是<li>
直接去掉多余的Fragment,将key直接加在循环返回的Driver组件上即可,React会自动将key传递给它的根节点<li>:
import React from "react" import Driver from "./Driver" import Card from "../../shared/components/interface/Card" import "./DriverList.css" const DriverList = (props) => { if (props.items.length === 0) { return ( <Card> <h2>No drivers found.</h2> </Card> ) } else { return ( <ul className='driver-list'> {props.items.map((driver) => { return ( <Driver key={driver.id} id={driver.id} permitno={driver.permitno} fname={driver.fname} lname={driver.lname} mailaddr1={driver.mailaddr1} mailaddr2={driver.mailaddr2} dateofbirth={driver.dateofbirth} driversex={driver.driversex} licenseidno={driver.licenseidno} dvrclass={driver.dvrclass} dvrpermit={driver.dvrpermit} endorsemnt={driver.endorsemnt} restricts={driver.restricts} expdate={driver.expdate} cmpldate={driver.cmpldate} numpoints={driver.numpoints} suspended={driver.suspended} driver_status={driver.driver_status} /> ) })} </ul> ) } } export default DriverList
情况2:Driver组件根元素不是<li>
如果Driver内部没有用<li>作为根节点,需要在循环时直接将<li>作为循环的子元素,把key加在<li>上,再包裹Driver组件:
{props.items.map((driver) => { return ( <li key={driver.id}> <Driver id={driver.id} permitno={driver.permitno} {/* 其他props */} /> </li> ) })}
核心原则:React要求列表循环产生的直接作为父容器(此处为ul)子元素的节点必须有唯一key,key不能加在嵌套的内部组件或多余的Fragment上。
内容的提问来源于stack exchange,提问作者Sionnach
相关产品推荐
相关产品推荐

