React中遍历对象数组内frontend子数组仅显示首个元素的问题
问题排查:React仅展示首个frontend技能ID的问题
问题描述
使用React展示技能数据时,成功访问到对象数组中的frontend属性,但遍历该数组时仅显示首个元素“HTML”的ID,无法展示其余技能ID。
外部数据文件
const skills = [ { frontend: [ { id: 'HTML', img: './images/skills/html5.svg' }, { id: 'CSS', img: './images/skills/css3.svg' }, { id: 'Javascript', img: './images/skills/javascript.svg' }, { id: 'Bootstrap', img: './images/skills/bootstrap.svg' }, { id: 'React JS', img: './images/skills/react.svg' }, { id: 'Flutter', img: './images/skills/flutter.svg' }, ], backend: [ { id: 'PHP', img: './images/skills/php.svg' }, { id: '.NET Core', img: './images/skills/net-core.svg' }, { id: 'Node JS', img: './images/skills/html5.svg' }, ], languages: [ { id: 'Java', img: './images/skills/java.svg' }, { id: 'Python', img: './images/skills/python.svg' }, { id: 'C#', img: './images/skills/csharp.svg' }, ], }, ]; export default skills;
原Home组件代码
import React, { useEffect, useState } from "react"; import "../styles/Home.css"; import Skills from "../data/Skills"; export const Home = () => { const [skills, setSkills] = useState([]); useEffect(() => { setSkills(Skills); }, []); const frontend = skills.map((element) => { return element.frontend; }); console.log(frontend); return ( <div className="home"> <div className="skills"> <h1>Skills</h1> {frontend.map((item, index) => { console.log(index) return <ul key={index}> <li>{item[index].id}</li> </ul>; })} </div> </div> ); };
问题原因
- 数据结构处理错误:外部导出的
skills是一个仅包含单个对象的数组,使用skills.map()处理后,frontend变量会变成二维数组[[...所有frontend元素]],而非一维数组。 - 渲染逻辑错误:在渲染时,
frontend.map()只会循环一次(因为外层数组只有一个元素),此时index=0,item[index].id等价于item[0].id,自然只能取到第一个元素“HTML”的ID。
解决方案
优化方案一:简化数据处理逻辑(推荐)
直接提取数组中唯一对象的frontend属性,避免不必要的map操作:
import React, { useState } from "react"; import "../styles/Home.css"; import Skills from "../data/Skills"; export const Home = () => { // 直接用Skills初始化state,省去useEffect const [skills, setSkills] = useState(Skills); // 取第一个元素的frontend数组,为空时返回空数组避免报错 const frontend = skills.length > 0 ? skills[0].frontend : []; return ( <div className="home"> <div className="skills"> <h1>Skills</h1> // 直接遍历一维的frontend数组,用元素自身的id作为key(比index更可靠) {frontend.map((skill) => ( <ul key={skill.id}> <li>{skill.id}</li> </ul> ))} </div> </div> ); };
优化方案二:展平二维数组(兼容原逻辑)
如果需要保留原skills.map()的处理方式,可通过flat()方法展平二维数组,再进行渲染:
// 修改渲染部分代码 {frontend.flat().map((skill) => ( <ul key={skill.id}> <li>{skill.id}</li> </ul> ))}
内容的提问来源于stack exchange,提问作者Lazare
相关产品推荐
相关产品推荐

