React收藏电影组件map函数报错问题排查求助
问题:收藏电影组件map函数失效及API数据获取异常
错误信息
错误1
favorite.jsx:32 Uncaught TypeError: Cannot read properties of undefined (reading 'map') at Favorite (favorite.jsx:32:1) at renderWithHooks (react-dom.development.js:16305:1) at updateFunctionComponent (react-dom.development.js:19588:1) at beginWork (react-dom.development.js:21601:1) at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1) at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1) at invokeGuardedCallback (react-dom.development.js:4277:1) at beginWork$1 (react-dom.development.js:27451:1) at performUnitOfWork (react-dom.development.js:26557:1) at workLoopSync (react-dom.development.js:26466:1)
错误2
favorite.jsx:32 Uncaught TypeError: movies.map is not a function at Favorite (favorite.jsx:32:1) at renderWithHooks (react-dom.development.js:16305:1) at updateFunctionComponent (react-dom.development.js:19588:1) at beginWork (react-dom.development.js:21601:1) at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1) at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1) at invokeGuardedCallback (react-dom.development.js:4277:1) at beginWork$1 (react-dom.development.js:27451:1) at performUnitOfWork (react-dom.development.js:26557:1) at workLoopSync (react-dom.development.js:26466:1)
相关代码
Favorite组件核心代码
import { getAllFavorite } from "../../service/favServics"; import { useState, useEffect } from "react"; import PageHeader from "../common/pageHeader"; import FavoriteChiled from "./favoritechild"; function Favorite() { const [favorite, setFavorite] = useState([]); const [movies, setMovies] = useState([]); const [data, setData] = useState([]); async function getAll() { const { data } = await getAllFavorite(); setFavorite(data); for (let i = 0; i < data.length; i++) { const url = `http://www.omdbapi.com/?s=${data[i]}&apikey=aea06659`; const response = await fetch(url); const responseJson = await response.json(); const obj = responseJson.Search[0]; if (responseJson.Search) { setMovies(obj.Title); } } } useEffect(() => { getAll(favorite); }, []);
Favorite组件返回部分
<div className="row"> {movies.map((movie) => ( <FavoriteChiled movie={movie} /> ))} </div>
子组件FavoriteChiled代码
function FavoriteChiled(props) { let { movies } = props; return ( <> <div key={movies.imdbID} className="image-container d-flex justify-content-start m-3"> <img src={movies.Poster} alt="movie"></img> </div> </> ); }
问题原因
- 状态类型错误:
movies初始为数组,但循环中用setMovies(obj.Title)将其赋值为字符串,导致后续调用map时报错(字符串没有map方法)。 - 状态更新逻辑错误:循环中多次调用
setMovies会覆盖之前的状态,无法累加电影数据。 - Props不匹配:父组件传递的props是
movie,子组件解构的是movies,导致子组件无法获取正确数据。 - API请求未做异常处理:如果OMDb API返回的
responseJson.Search为空,直接访问responseJson.Search[0]会导致undefined错误。 - 无效参数传递:
getAll函数不需要接收favorite参数,当前调用getAll(favorite)属于无效传参。
解决方案
1. 修正Favorite组件的状态更新逻辑
function Favorite() { const [favorite, setFavorite] = useState([]); const [movies, setMovies] = useState([]); const [isLoading, setIsLoading] = useState(true); // 添加加载状态 async function getAll() { try { const { data } = await getAllFavorite(); setFavorite(data); const fetchedMovies = []; // 遍历收藏的电影标题,批量获取API数据 for (const title of data) { const url = `http://www.omdbapi.com/?s=${encodeURIComponent(title)}&apikey=aea06659`; const response = await fetch(url); const responseJson = await response.json(); // 检查是否有搜索结果,避免报错 if (responseJson.Search && responseJson.Search.length > 0) { fetchedMovies.push(responseJson.Search[0]); } } // 一次性更新movies状态 setMovies(fetchedMovies); } catch (error) { console.error("获取数据失败:", error); } finally { setIsLoading(false); } } useEffect(() => { getAll(); // 无需传参 }, []); // 渲染时处理加载状态 if (isLoading) { return <div>加载中...</div>; } return ( <div className="row"> {movies.map((movie) => ( <FavoriteChiled key={movie.imdbID} movie={movie} /> ))} </div> ); }
2. 修正子组件的Props接收
function FavoriteChiled(props) { // 匹配父组件传递的props名称 const { movie } = props; // 处理海报为空的情况 const posterUrl = movie.Poster !== "N/A" ? movie.Poster : "默认海报地址"; return ( <div key={movie.imdbID} className="image-container d-flex justify-content-start m-3"> <img src={posterUrl} alt={movie.Title} /> </div> ); }
关键优化点
- 使用临时数组
fetchedMovies收集所有API返回的电影数据,一次性调用setMovies更新状态,避免多次更新导致的状态覆盖。 - 添加
encodeURIComponent处理电影标题中的特殊字符,避免API请求失败。 - 增加加载状态和错误捕获,提升用户体验。
- 修正子组件的props名称匹配,避免数据未定义。
- 处理海报为"N/A"的情况,防止图片加载失败。
内容的提问来源于stack exchange,提问作者dor achinakar
相关产品推荐
相关产品推荐

