如何对API分页数据进行过滤并将所有结果存入React状态?
问题原因
你当前的代码存在两个核心问题:
- 每次请求完成后,直接用
setResultPhotos(photos)将新获取的照片数组覆盖了之前的state值,而非追加,因此最终只有最后完成的请求结果被保留。 - Axios请求是异步执行的,循环发起的多个请求完成顺序不确定,进一步加剧了结果被覆盖的问题。
另外还有个小细节:原代码中j < 7的循环边界会漏掉collections数组的最后一项"halloween",应该改为j < collections.length。
解决方案
方案1:逐个请求追加结果(保持原有循环逻辑)
通过函数式更新state,确保每次更新都基于最新的state值,将新过滤后的照片追加到数组中,同时添加组件卸载判断避免内存泄漏:
const [collections] = useState(["wedding", "outdoors", "portraits", "travel", "pets", "christmas", "products", "halloween"]); const [resultPhotos, setResultPhotos] = useState([]); const [pages, setPages] = useState(1); useEffect(() => { let isMounted = true; for (let j = 0; j < collections.length; j++) { for (let i = 0; i < 7; i++) { const url = `https://api.unsplash.com/search/photos?page=${i}&query=${collections[j]}&client_id=${accessKey}`; axios.get(url) .then((response) => { if (!isMounted) return; const filteredPhotos = response.data.results.filter(item => item.user.name === "Nathan Dumlao" ); // 函数式更新,追加新结果而非覆盖 setResultPhotos(prev => [...prev, ...filteredPhotos]); }) .catch(err => { console.error('请求出错:', err); }); } } // 组件卸载时终止未完成的更新 return () => { isMounted = false; }; }, []);
方案2:批量请求后统一更新(更可控)
用Promise.all收集所有请求,等待全部完成后一次性处理并更新state,适合需要确保结果完整性的场景:
const [collections] = useState(["wedding", "outdoors", "portraits", "travel", "pets", "christmas", "products", "halloween"]); const [resultPhotos, setResultPhotos] = useState([]); const [pages, setPages] = useState(1); useEffect(() => { let isMounted = true; const requests = []; // 收集所有请求Promise for (let j = 0; j < collections.length; j++) { for (let i = 0; i < 7; i++) { const url = `https://api.unsplash.com/search/photos?page=${i}&query=${collections[j]}&client_id=${accessKey}`; requests.push(axios.get(url)); } } // 等待所有请求完成后统一处理 Promise.all(requests) .then(responses => { if (!isMounted) return; const allFilteredPhotos = responses.reduce((acc, response) => { const filtered = response.data.results.filter(item => item.user.name === "Nathan Dumlao" ); return [...acc, ...filtered]; }, []); setResultPhotos(allFilteredPhotos); }) .catch(err => { console.error('部分请求失败:', err); }); return () => { isMounted = false; }; }, []);
注意事项
- 注意Unsplash API的调用频率限制,一次性发起56个请求可能触发限流,建议添加请求间隔或分页控制。
- 代码中修正了原变量名拼写错误
resulPhotos→resultPhotos。
内容的提问来源于stack exchange,提问作者Maco Acero
相关产品推荐
相关产品推荐

