React电影应用访问TMDB API指定电影属性报错问题
问题解决:React中访问TMDB返回数组指定元素属性时报错
问题根源
你遇到的Uncaught TypeError: Cannot read properties of undefined (reading 'id')错误,本质是React组件的渲染时机问题:
- 组件初始化时,
movieList的初始值是空数组[],此时movieList[1]等于undefined,直接访问undefined.id自然会抛出错误。 - 控制台打印四次是因为React组件会在初始化、
useEffect执行前后多次触发渲染:前两次请求还未完成,movieList还是空数组;后两次请求成功返回数据,setMovieList更新状态,数组才有内容。
而map能正常工作的原因是:空数组调用map时,回调函数不会执行,不会触发属性访问操作,等数组有数据后才会遍历渲染。
解决方案
以下几种方法都能解决这个问题,按需选择:
1. 使用可选链操作符(推荐)
在访问嵌套属性前加上?.,当左侧值为undefined或null时,表达式会直接返回undefined,不会抛出错误:
// 控制台打印修改 console.log(movieList[1]?.id) // 渲染部分修改 <img alt="" style={{width:"300px", marginLeft:"10px", marginTop:"10px"}} src={`https://image.tmdb.org/t/p/w500${movieList[1]?.poster_path || ''}`} />
这里加上|| '',可以避免poster_path为undefined时生成无效的URL。
2. 条件渲染(短路求值)
先判断movieList[1]是否存在,再执行后续操作:
// 渲染部分修改 {movieList[1] && ( <img alt="" style={{width:"300px", marginLeft:"10px", marginTop:"10px"}} src={`https://image.tmdb.org/t/p/w500${movieList[1].poster_path}`} /> )}
只有当movieList[1]为真(即存在)时,才会渲染这个img标签。
3. 添加加载状态
如果需要在请求完成前给用户反馈,可以增加一个加载状态:
function Movie() { const [movieList, setMovieList] = useState([]) const [loading, setLoading] = useState(true) // 新增加载状态 useEffect(() => { const getMovieList = async () => { const {data} = await tmdb.get('/discover/movie?') setMovieList(data.results) setLoading(false) // 请求完成后关闭加载状态 } getMovieList() },[]) if (loading) { return <div>加载中...</div> // 加载时显示提示 } return ( <div> {movieList.map((movie) => ( <img alt="" style={{width:"300px", marginLeft:"10px", marginTop:"10px"}} src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}/> ))} <img alt="" style={{width:"300px", marginLeft:"10px", marginTop:"10px"}} src={`https://image.tmdb.org/t/p/w500${movieList[1].poster_path}`} /> </div> ) }
这种方式可以确保渲染img时,movieList已经有数据了。
内容的提问来源于stack exchange,提问作者whitechoco
相关产品推荐
相关产品推荐

