You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React渲染数据库技能组件报错:Objects are not valid as a React child

问题分析与解决方案

错误根源

报错Objects are not valid as a React child (found: object with keys {})主要来自两个问题:

  • 数据库返回的部分技能名称与handleSkillsChips的switch分支不匹配(比如Express.js、React、Sequelize等),虽有default分支兜底,但如果<Default />组件返回空对象而非合法JSX元素,就会触发错误。
  • 代码存在冗余的jobsSkills定义,且渲染技能时未给动态元素添加key,可能引发额外渲染异常。

修复步骤

1. 统一技能名称匹配逻辑

针对数据库返回的技能,补充/调整switch分支,或通过字符串归一化处理消除名称差异:

const handleSkillsChips = (skill) => {   
    // 统一处理后缀,避免.js导致的匹配失败
    const normalizedSkill = skill.replace('.js', '');
    switch(normalizedSkill) {
      case 'Angular': return <Angular />;
      case 'AWS': return <AWS />;
      case 'Bootstrap': return <Bootstrap />;
      case 'C++': return <Cplus />;
      case 'CSS': return <CSS />;
      case 'Express': return <Express />; // 匹配Express.js
      case 'GitHub': return <Github />;
      case 'GraphQL': return <GraphQL />;
      case 'HTML': return <Html />;
      case 'JAVA': return <Java />;
      case 'JavaScript': return <JavaScript />;
      case 'MongoDB': return <MongoDB />;
      case 'MySQL': return <MySql />;
      case 'Node': return <NodeJS />; // 匹配Node.js
      case 'PHP': return <PHP />;
      case 'Python': return <Python />;
      case 'React': return <ReactJS />; // 匹配React
      case 'Rust': return <Rust />;
      case 'SQL': return <SQL />;
      case 'Vue': return <Vue />; // 匹配Vue.js
      case 'WordPress': return <Wordpress />;
      // 新增未覆盖的技能分支
      case 'Sequelize': return <Sequelize />;
      case 'Handlebars': return <Handlebars />;
      default: 
        // 兜底返回合法的MUI Chip组件,而非空对象
        return <Chip label={skill} variant="outlined" />;
    }
  }

2. 优化代码结构,移除冗余定义

直接在渲染时使用job.skills,无需提前生成jobsSkills数组,同时给动态元素添加唯一key:

const Listing = () => {
    const {loading, data} = useQuery(GET_JOBS);
    const jobs = data?.jobs || [];

    return (
      <div>
        { loading?
          <div>Loading job listings....</div>: 
          <div> 
            {jobs.map((job, jobIndex) => (      
            <Card key={jobIndex} className="col-8 mx-auto mb-4">
              <Card.Header>                
                {job.skills.map((skill) => (
                  <span key={skill} className="mr-1">
                    {handleSkillsChips(skill)}
                  </span>
                ))}                
              </Card.Header>
              <Card.Body>
                <Card.Title>{job.title}</Card.Title>
                <Card.Subtitle className="mb-2 text-muted">Tech Builders, Inc.</Card.Subtitle>
                <Card.Subtitle className="mb-2 text-muted">Atlanta, GA</Card.Subtitle>
                <Card.Text>"{job.description}"</Card.Text>
                <Button variant="primary" id="applyBtn" href={`//${job.link}`} target="_blank">Apply Here!</Button>{' '}
                <Button variant="primary" id="applyBtn" href={`//${job.link}`} target="_blank">Comment</Button>{' '}
              </Card.Body>
              <Card.Footer className="text-muted"> This job was posted on {job.createdAt}</Card.Footer>
            </Card>
              ))}
          </div>
        }   
      </div>
)}            

3. 确保兜底组件返回合法JSX

如果使用自定义<Default />组件,必须保证它返回有效的React元素,例如:

const Default = ({ skill }) => {
  return <Chip label={skill} color="default" />;
};

核心注意事项

  • 始终给map生成的元素添加唯一key,避免React渲染警告。
  • 通过字符串归一化(如去除后缀、统一大小写)消除数据库与前端的名称差异。
  • default分支必须返回合法JSX元素,禁止返回空对象或非React子节点类型。

内容的提问来源于stack exchange,提问作者DSwecker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 11:43:11