Next.js/React/JavaScript中合并两个API对象到状态数组的问题
如何合并两个API数据为对象数组?当前第二个数据覆盖第一个的问题解决
我从两个API获取到两个对象,分别存入两个不同的state,想要第三个state是包含这两个对象的数组,但现在第二个对象会覆盖第一个,无法推入数组,请问哪里错了?
错误代码如下:
export default function useFetchNaveNarCatagoriesThatAreNotGenres() { const [trending, setTrending] = useState(); const [toprated, setToprated] = useState(); const [trendingandtopratedcombined, setTrendingandtopratedcombined] = useState([]); useEffect(() => { async function APIfetch() { const response = await fetch( `https://api.themoviedb.org/3/trending/all/day?api_key=f70b3ca617a5d8978429e375c55a4fa2` ); const fetchedtrending = await response.json(); setTrending(fetchedtrending); setTrendingandtopratedcombined(fetchedtrending) console.log( "This is me testing my fetch trending", fetchedtrending ); } APIfetch(); }, []); useEffect(() => { async function APIfetch() { const response = await fetch( `https://api.themoviedb.org/3/movie/top_rated?api_key=f70b3ca617a5d8978429e375c55a4fa2&language=en-US&page=1` ); const fetchedtoprated = await response.json(); console.log( "This is me testing my fetch toprated", fetchedtoprated ); setToprated(fetchedtoprated); setTrendingandtopratedcombined[...trendingandtopratedcombined, fetchedtoprated]); } APIfetch(); }, []); console.log("Testing my Final", trendingandtopratedcombined) }
问题根源
- 初始赋值错误:第一个
useEffect里直接把单个对象fetchedtrending赋值给了数组state,导致后续无法正确追加元素,应该初始存入数组[fetchedtrending]。 - setState语法错误:第二个
useEffect里调用setTrendingandtopratedcombined时少了括号,正确写法是setTrendingandtopratedcombined(...)。 - 异步state更新竞态:直接使用
trendingandtopratedcombined可能拿不到最新state值,因为React的state更新是异步的,必须用函数式更新获取上一轮state。 - 并行请求的不确定性:两个
useEffect并行执行,可能第二个请求完成时第一个的state还没更新,导致合并时丢失数据。
修正方案一:修复原有逻辑
export default function useFetchNaveNarCatagoriesThatAreNotGenres() { const [trending, setTrending] = useState(); const [toprated, setToprated] = useState(); const [trendingandtopratedcombined, setTrendingandtopratedcombined] = useState([]); useEffect(() => { async function APIfetch() { const response = await fetch( `https://api.themoviedb.org/3/trending/all/day?api_key=f70b3ca617a5d8978429e375c55a4fa2` ); const fetchedtrending = await response.json(); setTrending(fetchedtrending); // 初始存入数组 setTrendingandtopratedcombined(prev => [...prev, fetchedtrending]); console.log("This is me testing my fetch trending", fetchedtrending); } APIfetch(); }, []); useEffect(() => { async function APIfetch() { const response = await fetch( `https://api.themoviedb.org/3/movie/top_rated?api_key=f70b3ca617a5d8978429e375c55a4fa2&language=en-US&page=1` ); const fetchedtoprated = await response.json(); console.log("This is me testing my fetch toprated", fetchedtoprated); setToprated(fetchedtoprated); // 函数式更新获取上一轮state,避免竞态 setTrendingandtopratedcombined(prev => [...prev, fetchedtoprated]); } APIfetch(); }, []); console.log("Testing my Final", trendingandtopratedcombined); }
修正方案二:合并请求提升效率
直接在一个useEffect里并行发起两个请求,一步合并成数组,彻底避免竞态问题:
export default function useFetchNaveNarCatagoriesThatAreNotGenres() { const [trending, setTrending] = useState(); const [toprated, setToprated] = useState(); const [trendingandtopratedcombined, setTrendingandtopratedcombined] = useState([]); useEffect(() => { async function fetchAllData() { // 并行发起两个请求,减少等待时间 const [trendingRes, topRatedRes] = await Promise.all([ fetch(`https://api.themoviedb.org/3/trending/all/day?api_key=f70b3ca617a5d8978429e375c55a4fa2`), fetch(`https://api.themoviedb.org/3/movie/top_rated?api_key=f70b3ca617a5d8978429e375c55a4fa2&language=en-US&page=1`) ]); const fetchedtrending = await trendingRes.json(); const fetchedtoprated = await topRatedRes.json(); setTrending(fetchedtrending); setToprated(fetchedtoprated); // 直接合并为对象数组 setTrendingandtopratedcombined([fetchedtrending, fetchedtoprated]); console.log("trending data:", fetchedtrending); console.log("top rated data:", fetchedtoprated); } fetchAllData(); }, []); console.log("Testing my Final", trendingandtopratedcombined); }
内容的提问来源于stack exchange,提问作者Nowisthecode
相关产品推荐
相关产品推荐

