React开发电影趋势页:从单对象JSON API批量存数据出错求助
问题分析与修复方案
核心问题
你的代码存在几个关键问题导致了异常结果:
- 异步时序错误:调用
getData后立刻执行trends.push(movie),此时API请求还没完成,movie还是初始的空对象,所以数组里全是空值。 - 直接修改State:
trends.push(movie)是直接修改原State数组,React无法识别这种变更,后续setTrends(trends)传递的是同一个数组引用,不会触发正确的重新渲染。 - 闭包与重复更新:循环里多次调用
setTrends,每次拿到的trends都是初始的空数组(闭包特性),多次push后会导致数组长度超出预期。 - 单个State被覆盖:多个请求共享同一个
movieState,后完成的请求会覆盖之前的结果,即使等待请求完成,最终也无法正确收集所有电影数据。
修复后的代码
import { useState, useEffect } from 'react'; import axios from 'axios'; function MovieTrends() { const [trends, setTrends] = useState([]); const trendsTitles = ["dune", "annette", "cendrillon", "mon frere", "athena", "footloose"]; // 修改getData,让它返回请求结果,不再依赖单个movie state async function getData(title) { try { const response = await axios.get(`http://www.omdbapi.com/?apikey=[apikey]&t=${title}`); return response.data; } catch (error) { console.log(`获取电影${title}失败:`, error); return null; // 失败时返回null,避免影响整体结果 } } useEffect(() => { async function fetchAllMovies() { // 使用Promise.all并行处理所有请求,等待全部完成 const moviePromises = trendsTitles.map(title => getData(title)); const movies = await Promise.all(moviePromises); // 过滤掉请求失败的null值,再更新state setTrends(movies.filter(movie => movie !== null)); } fetchAllMovies(); }, []); return ( <div> {/* 这里渲染你的电影列表 */} {trends.map((movie, index) => ( <div key={index}> <h3>{movie.Title}</h3> <p>{movie.Year}</p> </div> ))} </div> ); } export default MovieTrends;
关键改动说明
- 让
getData返回数据:不再用setMovie存储单个电影,而是直接返回请求结果,避免状态被覆盖。 - 用
Promise.all处理并发请求:一次性发起所有请求,等待全部完成后再统一更新State,保证数据完整且只触发一次渲染。 - 避免直接修改State:通过生成新的电影数组来更新
trends,符合React的State更新规范。 - 错误处理优化:请求失败时返回
null,后续过滤掉无效数据,避免错误数据影响页面渲染。
内容的提问来源于stack exchange,提问作者Zen
相关产品推荐
相关产品推荐

