
React 报错“Each child in a list should have a unique ‘key’ prop”通常是因为 key 未设置在直接子元素上,或被错误地放在了条件渲染的内部节点中;本文通过真实案例解析 key 的作用域规则、Fragment 正确用法及常见陷阱。
react 报错“each child in a list should have a unique ‘key’ prop”通常是因为 `key` 未设置在**直接子元素**上,或被错误地放在了条件渲染的内部节点中;本文通过真实案例解析 key 的作用域规则、fragment 正确用法及常见陷阱。
在 React 列表渲染中,key 是一个特殊且必需的属性,它并非传递给组件的普通 props,而是由 React 内部用于识别列表中每个元素的稳定标识符。关键原则是:key 必须赋给由 map() 直接返回的 JSX 元素(即列表的直接子节点),而非其内部嵌套结构。
回顾原始代码问题:
{Object.entries(userRoleMenu[UserRole]).map((item, index) => <>
{item[0] === 'fpv' ? (
<MenuItem key={item[0]} /* ❌ 错误:key 在条件分支内,但 Fragment <> 没有 key */ />
) : (
<MenuItem key={item[0]}>{item[0]}</MenuItem>
)}
</>)}此处根本性错误在于:...>(即 React.Fragment)作为 map 的返回值,是列表的直接子节点,但它本身没有 key。而内部的
✅ 正确解法是将 key 显式赋予 React.Fragment(或使用带 key 的
<MenuList width={'148px'}>
{Object.entries(userRoleMenu[UserRole]).map((item, index) => (
<React.Fragment key={item[0]}>
{item[0] === 'fpv' ? (
<MenuItem
_hover={{ backgroundColor: 'gray.50' }}
onClick={() => handleMenuClick(item)}
>
{/* fpv 专属内容,例如图标或自定义标签 */}
<Icon as={FpvIcon} mr={2} />
FPV 控制台
</MenuItem>
) : (
<MenuItem
_hover={{ backgroundColor: 'gray.50' }}
onClick={() => handleMenuClick(item)}
>
{item[0]}
</MenuItem>
)}
</React.Fragment>
))}
</MenuList>⚠️ 注意事项:
- key 不可动态生成(如 key={Math.random()})或使用 index(当列表可能增删/重排时会导致状态错乱);优先使用数据本身的稳定 ID(如 item[0] 作为菜单键名是合理选择);
- 条件渲染中若需返回多个并列元素,必须包裹在带 key 的 Fragment 中,不可省略;
- onClick={handleMenuClick(item)} 是常见错误写法(立即执行函数),应改为 onClick={() => handleMenuClick(item)} 或 onClick={useCallback(() => handleMenuClick(item), [item])} 防止重复创建函数;
- 若 item[0] 存在重复风险(如后端数据异常),建议添加校验或改用组合键(如 ${item[0]}-${index})作为兜底方案。
总结:key 是 React 协调列表更新的“锚点”,它的位置必须精准落在 map 返回的 JSX 顶层节点上。理解这一机制,能从根本上避免 “unique key error”,并写出更健壮、可维护的列表渲染逻辑。









