React传递props报错objects are not valid as a react child
问题背景
React初学者基于列表数据向子组件传递props做渲染时,触发objects are not valid as a react child报错:父组件中打印待传递的值均为字符串类型,但子组件中接收到的参数为对象类型,排查代码和正常示例的差异未果。
涉及代码如下:
父组件(UnorderedListNavBar)代码
const navbarCollection = [ { id: 1, item: 'Home', ref: '#'}, { id: 2, item: 'Search', ref: '#'}, { id: 3, item: 'Login', ref: '#'}, { id: 4, item: 'Register', ref: '#'}, ]; function UnorderedListNavBar() { return ( <div id='wrapper-navBarList'> <ul className='navbar-nav mr-auto'> { navbarCollection.map((menuItem) => { return (<ListItem key={menuItem.id} mykey={menuItem.item} value={menuItem.ref} />); }) } </ul> </div> ) } export default UnorderedListNavBar;
子组件(ListItem)代码
function ListItem(id, type, href) { return ( <div id='wrapper-navBarListItem'> <li className='list-item active'> <a className='nav-link' href={href}>test</a> </li> </div> ) } export default ListItem;
问题根因
报错的核心原因是对React函数组件的props接收规则理解错误,共涉及2个关键问题:
- 函数组件的参数规则错误:React不会把传给组件的多个属性拆成多个独立参数传入组件,所有传入的自定义属性会被统一打包为一个props对象,作为函数的第一个参数传入。你写的
function ListItem(id, type, href)中,只有第一个形参id能拿到值,这个值就是完整的props对象,后面的type、href全为undefined——这就是你在子组件打印参数拿到对象的原因。 - 传参属性名和接收名不匹配:父组件传给ListItem的自定义属性是
mykey和value,根本没有传递名为href的属性,就算正确接收了props对象,直接访问href也拿不到目标值。
补充:
key是React框架内部使用的特殊属性,不会被放入props对象透传给子组件,无法在组件内部读取到key的值。
修复方案
修改子组件的props接收逻辑,从第一个参数(即props对象)中读取传入的对应字段即可,推荐两种写法:
- 直接通过props对象访问属性
function ListItem(props) { return ( <div id='wrapper-navBarListItem'> <li className='list-item active'> {/* 父组件传入的链接存在props.value,菜单名存在props.mykey */} <a className='nav-link' href={props.value}>{props.mykey}</a> </li> </div> ) } export default ListItem;
- 参数位置直接解构props(更简洁,推荐)
// 直接从props对象中解构出需要的字段 function ListItem({ mykey, value }) { return ( <div id='wrapper-navBarListItem'> <li className='list-item active'> <a className='nav-link' href={value}>{mykey}</a> </li> </div> ) } export default ListItem;
可选优化
当前父组件传递的属性名mykey、value语义性差,可以调整为和业务含义匹配的命名,降低后续维护成本:
- 父组件传参改为:
<ListItem key={menuItem.id} menuName={menuItem.item} href={menuItem.ref} /> - 子组件对应解构改为:
function ListItem({ menuName, href }) { ... },内部直接用href、menuName即可。
内容的提问来源于stack exchange,提问作者AoXNeR
相关产品推荐
相关产品推荐

