React中使用API返回的对象数组更新state并传递至子组件时出现‘对象不能作为React子元素’报错的问题排查
问题分析与解决方案
Hey Angela, 我一眼就看到问题出在哪了——你的MovieList组件里的testFunction逻辑搞反了,这才导致React抛出"对象不能作为子元素渲染"的错误。让我给你拆解清楚:
为什么会报错?
错误提示Objects are not valid as a React child (found: object with keys {id, name})说明你在某个地方让React直接渲染了一个{id, name}的对象,而React不知道怎么处理这种类型。
看你的testFunction代码:
const testFunction = (movieGenreIds) => { const matchMovieGenresAndGenreIds = genres.map((genreId) => { const matchedGenres = movieGenreIds.find((movieGenre) => { return movieGenre.id === genreId }) return matchedGenres }) // ... }
这里有两个关键错误:
- 你把
genres数组里的每一项(是个完整的{id, name}对象)命名为genreId,这完全是变量名误导,后面的逻辑全错了。 movieGenreIds是电影的分类ID数组(比如[28, 12]),里面的元素是数字,根本没有id属性,你写的movieGenre.id === genreId相当于拿undefined和一个对象比较,永远匹配不上。
这种错误逻辑要么返回一堆undefined,要么在某些情况下意外传递了对象给MovieItem,触发React的渲染错误。
正确的解决方案
你真正需要的逻辑是:根据电影的分类ID数组,从genres对象数组里找到对应的分类名称,而不是反过来遍历genres去匹配ID。
修改MovieList里的testFunction:
const testFunction = (movieGenreIds) => { // 遍历电影的每个分类ID,找到对应的分类名称 return movieGenreIds .map(genreId => { // 在genres中匹配ID一致的分类对象 const matchedGenre = genres.find(genre => genre.id === genreId); // 找到就返回名称,没找到就返回空字符串(避免undefined) return matchedGenre ? matchedGenre.name : ''; }) // 过滤掉空字符串(处理无匹配的情况) .filter(name => name); };
然后恢复你最初的setState写法,直接把完整的分类对象数组赋值给genreOptions:
componentDidMount() { this.getGenreList().then((response) => { console.log(response) this.setState({ genreOptions: response}); }); }
最后,为了让分类名称渲染更美观,在MovieItem里把数组转成逗号分隔的字符串:
<div>{movieGenres.join(', ')}</div>
为什么另一个API能成功?
因为另一个API的处理逻辑没有这种方向错误,它要么返回的数据可以直接渲染,要么处理数据的逻辑是正确的,没有让React去渲染对象类型。
内容的提问来源于stack exchange,提问作者Angela Inniss
相关产品推荐
相关产品推荐

