React电影应用中video状态无法使用map函数,如何修复?
问题分析与修复方案
核心问题
- 返回值类型不匹配:
fetchVideo返回的是单个视频对象(respone.data.results[1]),但你初始化video为数组,后续试图用map遍历单个对象,触发报错。 - 异步请求处理错误:
fetchVideo是异步函数,直接调用setVideo(fetchVideo(id))会把Promise对象赋值给video,而非实际数据,Promise没有map方法。 - 未处理初始空状态:
coming在数据加载完成前可能为undefined,直接访问其属性会触发报错。 - 错误处理逻辑缺陷:
fetchVideo的catch块返回error对象,若请求失败,video会变成error对象,引发后续渲染错误。
修复步骤
- 调整返回值为数组:若要保留
map遍历,把单个视频对象包装成数组;如果需要所有视频,直接返回response.data.results。 - 正确处理异步数据流:在
useEffect中用async/await等待异步请求完成后再更新状态。 - 添加空状态保护:用可选链
?.或条件渲染处理coming未加载完成的情况。 - 优化错误返回值:catch块返回空数组,保证
video始终是数组类型。
修改后的完整代码
import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useParams } from 'react-router-dom' import { fetchMovie } from '../../../manage/action' import style from './style.module.css' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faStar } from '@fortawesome/free-solid-svg-icons' import Youtube from 'react-youtube' import { movieList } from '../../../service/api/api' function ContentComing() { const { id } = useParams() const dispatch = useDispatch() const [video, setVideo] = useState([]) const { coming } = useSelector((state) => state.upComing) const fetchMovieUpComing = async (comingId) => { await dispatch(fetchMovie(comingId)) } const fetchVideo = async (movieId) => { try { const response = await movieList.get(`/movie/${movieId}/videos?api_key=${import.meta.env.VITE_TMDB_KEY}`) // 若只需第二个视频则包装为数组,需全部视频直接返回response.data.results return response.data.results.length > 1 ? [response.data.results[1]] : [] } catch (error) { console.error('获取视频失败:', error) return [] // 报错时返回空数组,保证video类型稳定 } } useEffect(() => { const initData = async () => { await fetchMovieUpComing(id) const videoData = await fetchVideo(id) setVideo(videoData) } initData() }, [id, dispatch]) return ( <> <div className={style['wrapper']}> {coming ? ( <div className={style['detail-movie']}> <div className={style['image-movie']}> <img src={`${import.meta.env.VITE_IMG_PATH}${coming.poster_path}`} alt='poster' /> </div> <div className={style['content-movie']}> <p className={style.title}>Title: {coming.title}</p> <div className={style['rating']}> <FontAwesomeIcon icon={faStar} className={style['icon']} size='2x' /> {coming.vote_average} </div> <p>Release Date: {coming.release_date}</p> <hr /> <div className={style['genre']}> <p>Genre:</p> {coming.genres?.map((item) => ( <p key={item.id}>{item.name}</p> ))} </div> <p>Language: {coming.original_language}</p> <p>Overview: {coming.overview}</p> <p>Popularity: {coming.popularity}</p> </div> </div> ) : ( <p>加载中...</p> )} <div className={style['video-movie']}> {video.map((item, index) => ( <Youtube key={index} videoId={item.key} /> ))} </div> </div> </> ) } export default ContentComing
额外说明
- 移除了冗余的
append_to_response=videos参数,/movie/{id}/videos接口本身已返回视频列表。 - 给
useEffect添加了必要依赖项,符合React Hooks规则,避免lint警告。 - 添加加载状态提示,优化用户体验。
内容的提问来源于stack exchange,提问作者Hovi Sohibul Wafa
相关产品推荐
相关产品推荐

