React渲染嵌套数组对象时触发Objects are not valid as a React child错误
解决React中嵌套数组对象渲染的"Objects are not valid as a React child"错误
问题重现
在React项目中渲染嵌套数组内的对象(展示name与value)时,反复触发Objects are not valid as a React child错误,相关代码如下:
状态数据
const [avail, setavail] = useState({ firstName: '', lastName: '', mobileNumber: '', doctorId: '', avalabilities: [ { availabilityId: '', day: [ { name: 'Sunday', value: 'Sunday' }, { name: 'Monday', value: 'Monday' }, { name: 'Tuesday', value: 'Tuesday' }, { name: 'Wednesday', value: 'Wednesday' }, { name: 'Thursday', value: 'Thursday' }, { name: 'Friday', value: 'Friday' }, { name: 'Saturday', value: 'Saturday' }, ], isChecked: false, checked: false, allChecked: false, error: null } ] });
原渲染JSX代码
{avail.avalabilities.map((av, avIndex) => ( <div key={av.availabilityId}> {av.day.map((item, index) => ( <div key={index}> <input checked={item?.checked || false} name={item.name} value={item.value} onChange={(e) => checkedHandler(e, avIndex, index) } type="checkbox" id={item.value} /> {console.log(item.name)} {console.log(item.value)} <label htmlFor={item.value}>{item.name}</label> </div> ))}
原复选框处理函数
const checkedHandler = (e, avIndex, index) => { console.log(e.target.checked, avIndex, index); setavail((prev) => { let newState = { ...prev }; newState.avalabilities[avIndex].day[index].checked = e.target.checked; return newState; }); };
错误原因分析
- 状态更新的浅拷贝问题:React状态要求不可变更新,原处理函数仅浅拷贝了外层对象,但
avalabilities数组和内部的day数组都是引用类型,直接修改数组内的对象会导致React无法正确检测状态变化,进而引发渲染异常。 - JSX标签未闭合:原渲染代码中最外层的
<div>标签没有闭合,这会导致React解析JSX时出错,间接触发对象渲染的错误提示。
解决方案
1. 修复状态更新的不可变处理
修改checkedHandler函数,对嵌套的数组和对象进行深拷贝,确保每次状态更新都创建新的引用:
const checkedHandler = (e, avIndex, index) => { const isChecked = e.target.checked; setavail((prev) => ({ ...prev, avalabilities: prev.avalabilities.map((av, idx) => { if (idx !== avIndex) return av; return { ...av, day: av.day.map((item, dayIdx) => { if (dayIdx !== index) return item; return { ...item, checked: isChecked }; }) }; }) })); };
2. 闭合JSX标签
确保所有JSX标签正确闭合,补充原代码中缺失的</div>:
{avail.avalabilities.map((av, avIndex) => ( <div key={av.availabilityId || avIndex}> {/* 为空key添加兜底值 */} {av.day.map((item, index) => ( <div key={index}> <input checked={item?.checked || false} name={item.name} value={item.value} onChange={(e) => checkedHandler(e, avIndex, index)} type="checkbox" id={item.value} /> <label htmlFor={item.value}>{item.name}</label> </div> ))} </div> {/* 补充闭合标签 */} ))}
3. 移除冗余渲染代码
原JSX中直接嵌入{console.log(item.name)}这类表达式属于冗余代码,建议移除,避免干扰渲染逻辑。
验证说明
修改后,状态更新会遵循React的不可变原则,JSX结构也合法,此时渲染嵌套数组中的item.name和item.value不会再触发对象渲染的错误,复选框的选中状态也能正确同步到状态中。
内容的提问来源于stack exchange,提问作者Disha Singh
相关产品推荐
相关产品推荐

