
在 react 中使用 map 渲染列表时,必须为每个直接子元素(而非其内部元素)提供唯一且稳定的 key 属性;若返回 fragment 或混合节点,key 应作用于最外层容器组件。
你遇到的警告 Each child in a list should have a unique 'key' prop 并非因为没写 key,而是因为 key 没有被放在 React 列表渲染的直系子节点上。
在你的原始代码中:
words.map((word, index) => {
if (index !== words.length - 1) {
return <>{word} // >;
} else {
return {word};
}
})问题在于:> 是 React.Fragment 的简写,但它本身不可接收 key 属性(空 Fragment 不支持 props)。你把 key={word} 错误地加在了 上,而该 并非 map 返回数组的顶层元素——真正作为 map 结果项的顶层节点是 Fragment。React 要求 key 必须由 map 返回的每个顶层 JSX 元素自身携带,而不是其子元素。
✅ 正确做法:将 key 显式赋予 React.Fragment(或其简写 > 的替代方案——带 key 的
import React from 'react';
function StyleWords({ words, ...props }) {
return words.map((word, index) => {
if (index !== words.length - 1) {
// ✅ key 必须加在 Fragment 上(不能加在 span 上)
return (
{word} //
);
} else {
// ✅ 最后一项直接返回带 key 的 span(它本身就是顶层节点)
return {word};
}
});
}⚠️ 注意事项:
- 不要用 word 单独作 key:如果数组中存在重复单词(如 ['hello', 'world', 'hello']),key={word} 将导致 key 冲突,触发 React 警告甚至渲染异常。推荐组合索引:key={${word}-${index}}(适用于无动态增删场景);更健壮的方式是确保数据含唯一 ID,或使用 useId(React 18+)生成稳定标识。
-
Fragment 必须显式使用 React.Fragment 或
:空标签 ...> 不支持 key,这是常见误区。 - 避免在条件分支中混用不同根节点类型:本例中前几项返回 Fragment、最后一项返回 span,虽可行,但可优化为统一结构,提升可维护性:
// ✅ 更清晰统一的写法(推荐)
function StyleWords({ words, separator = ' // ' }) {
return words.map((word, index) => (
{word}
{index < words.length - 1 && {separator} }
));
}这样既保证 key 正确绑定,又语义清晰、易于扩展分隔符逻辑。记住核心原则:key 属于列表项的容器,不是内容元素。









