React渲染报错:Objects are not valid as a React child 求解
问题:React渲染Api4数组时触发对象无法作为React子元素的错误
错误信息
Uncaught Error: Objects are not valid as a React child (found: object with keys {0}). If you meant to render a collection of children, use an array instead.
Uncaught Error: Objects are not valid as a React child (found: object with keys {0, 1, 2, ...,43}). If you meant to render a collection of children, use an array instead.
组件代码
import React from 'react'; import axios from 'axios'; export default class Cou extends React.Component { state = { Api1: [], Api2: [], Api3: [], Api4:[], currentTask:"", } componentDidMount() { axios.get("https://assessment.api.vweb.app/users") .then(res => { const Api1 = res.data; this.setState({ Api1 }); }) axios.get("https://assessment.api.vweb.app/products") .then(res => { const Api2 = res.data; this.setState({ Api2}); }) axios.get("https://assessment.api.vweb.app/orders") .then(res => { const Api3 = res.data.map(item => ({...item, user_name: this.state.Api1.find(({user_id}) => user_id === item.user_id)?.name || "", product_name: this.state.Api2.find(({product_id}) => product_id === item.product_id)?.name|| "",})); this.setState({ Api3 }); }) } handleChange = (e) => { console.log(e.target.value); this.setState({ currentTask:e.target.value, }); }; show = () =>{ let cn = this.state.Api1.filter(m=>{return m.user_id == `${this.state.currentTask}`}).map(o=>{return((o.name))}) let cd = this.state.Api3.filter(person => { return person.user_id == `${this.state.currentTask}`}).map(n => {return (n.product_name)}) this.setState({ Api4:[{coustomer_name: {...cn}}, {coustomer_detail:{...cd}}] }) } render() { return ( <> <div> <input type ="text" onChange={this.handleChange}/> <button onClick={this.show}> Show history</button> {this.state.Api4.map(p=>{return (<p>{p.coustomer_name} {console.log(p.coustomer_name)} bought,</p>)})} {this.state.Api4.map(p=>{return (<p>{p.coustomer_detail} {console.log(p.coustomer_detail)}</p>)})} </div> </>) } }
问题原因
- 数据结构错误:
show函数中用{...cn}和{...cd}把数组转成了带索引键的对象(比如用户名称数组会变成{0: "用户名"}),React无法直接渲染对象作为子元素。 - 渲染逻辑错误:即使是数组,也不能直接在JSX中渲染,需要转成字符串或逐个渲染元素。
解决步骤
1. 修正Api4的数据存储
修改show函数,直接存储字符串和数组,避免转成对象:
show = () =>{ // 根据user_id取唯一用户名,用find替代filter+map更高效 const customerName = this.state.Api1.find(m => m.user_id === this.state.currentTask)?.name || '未知用户'; // 提取该用户的所有购买商品名称 const customerDetails = this.state.Api3.filter(person => person.user_id === this.state.currentTask) .map(n => n.product_name); // 调整Api4为包含单个对象的数组,统一存储用户信息和购买列表 this.setState({ Api4: [{ customerName, customerDetails }] }) }
2. 修正渲染逻辑
在render中正确渲染字符串和遍历数组:
render() { return ( <> <div> <input type ="text" onChange={this.handleChange}/> <button onClick={this.show}> Show history</button> {this.state.Api4.map((item, index) => ( <div key={index}> <p>{item.customerName} bought:</p> <ul> {item.customerDetails.map((product, idx) => ( <li key={idx}>{product}</li> ))} </ul> </div> ))} </div> </>) }
额外优化:修复异步请求顺序问题
原代码中三个axios请求并行,处理orders时Api1和Api2可能还未更新,导致关联名称为空。用Promise.all确保所有请求完成后再处理:
componentDidMount() { Promise.all([ axios.get("https://assessment.api.vweb.app/users"), axios.get("https://assessment.api.vweb.app/products"), axios.get("https://assessment.api.vweb.app/orders") ]).then(([usersRes, productsRes, ordersRes]) => { const Api1 = usersRes.data; const Api2 = productsRes.data; const Api3 = ordersRes.data.map(item => ({ ...item, user_name: Api1.find(({user_id}) => user_id === item.user_id)?.name || "", product_name: Api2.find(({product_id}) => product_id === item.product_id)?.name|| "", })); this.setState({ Api1, Api2, Api3 }); }) }
内容的提问来源于stack exchange,提问作者Vishesh Kumar
相关产品推荐
相关产品推荐

