React使用嵌套Map遍历Skills JSON时触发对象不可作为子元素报错的问题
报错根本原因
触发该报错的核心逻辑是:JSX 不允许将原生 JavaScript 对象作为子元素直接渲染,你两版实现都存在未提取对象具体字段、直接把对象塞入 JSX 花括号的问题,和嵌套 map 的遍历逻辑本身无关。
逐位置定位错误:
- 第一版代码的两处逻辑偏差:
- 内层技能遍历段:
<li key={skill.name}>{skill}</li>,花括号内的skill是带name键的原生对象,不是可渲染的字符串或合法React元素 - 外层分类遍历段:
<ul key={skills.type}>{skills}</ul>,花括号内直接塞入了整个分类对象(包含type、skill数组的节点),既没有把内层生成的li列表渲染到ul容器中,又额外引入了非法的对象子元素
- 内层技能遍历段:
- 第二版代码未解决问题的原因:
你在内层生成的li标签中,依然写的是{skill},也就是还是把整个{name: "xxx"}的对象塞在li内部,外层嵌套多少span、div做包装都没有用——li节点本身的子元素就是非法对象,必然触发完全相同的报错。
你之前测试单层遍历渲染type字段功能正常,本质是因为skills.type是字符串类型,属于React合法的子元素渲染范畴,刚好和内层渲染时传入非法对象的行为形成了对比。
正确修正方案
修正只需要遵循两个规则:
- 所有放在JSX花括号内的内容,必须提取对象的具体字符串字段,禁止直接把原生对象当子元素传入
- 嵌套map的返回值要逐层传递:外层遍历拿到分类对象后,把内层map生成的技能列表渲染到对应容器中,不要把外层的原始分类对象当子元素塞进去
修正后的完整实现代码:
const skillsList = this.props.data.skills.map((category) => { // 内层遍历单个分类下的所有技能项 const skillItems = category.skill.map((skill) => { // 注意:这里必须取skill.name的字符串值,不能直接渲染skill对象 return <li key={skill.name.trim()}>{skill.name}</li> }) return ( <div key={category.type}> <h3>{category.type}</h3> <ul> {skillItems} </ul> </div> ) })
挂载到页面时,直接渲染生成的结构即可,不需要嵌套多余的ul标签:
<div className="bars"> {skillsList} </div>
额外提示:原JSON数据里BitBucket的字段值前带了空格,渲染前用trim()处理可以避免key重复、显示带多余空格的问题。
内容的提问来源于stack exchange,提问作者Jeffrey
相关产品推荐
相关产品推荐

