React中useEffect内用setState存请求数据 不加定时器无法打印问题求助
问题根源
- 异步请求处理逻辑错误:你在发起异步请求的同时就直接调用了
setGames(gamesArray),此时所有接口请求还未返回结果,你存入状态的是还没填充数据的空数组。后续接口返回后往gamesArraypush数据属于修改同一数组的引用,React检测不到引用变化就不会触发重渲染,所以你只能靠定时器、热重载才能看到数据。 - 并发异步请求没有统一等待逻辑:6个接口请求是并行发起的,你没有等所有请求都完成就更新状态,自然拿不到完整的返回结果。
修正方案
调整useEffect里的请求逻辑,用Promise.all等待所有请求完成后再统一更新状态即可,不需要额外加定时器和监听用的ref:
function Groups() { const [gamesD, setGames] = useState([]); const groups = [ 'EURO Grp. A', 'EURO Grp. B', 'EURO Grp. C', 'EURO Grp. D', 'EURO Grp. E', 'EURO Grp. F', ]; useEffect(() => { const instance = axios.create({ baseURL: server }); // 生成所有请求的Promise数组 const requestList = groups.map(group => instance.get(`Euro_events?grp=${group}`).then(res => res.data) ) // 等待所有请求完成后统一更新状态 Promise.all(requestList).then(allData => { setGames(allData) // 此处直接就能打印到完整数据 console.log(allData[0]?.[0]?.eventname) }) }, []); function logEventsArray(el) { console.log('games'); } // JSX渲染时加非空判断,避免数据未返回时报错 return ( <div> {gamesD.map((groupGames, groupIndex) => ( <div key={groupIndex}> <h3>{groups[groupIndex]}</h3> {groupGames.map((game, gameIndex) => ( <div key={game.id ?? gameIndex}>{game.eventname}</div> ))} </div> ))} </div> ) }
注意事项
- 渲染列表时要给每一项加唯一key属性,避免React渲染异常
- 访问嵌套数据时用可选链
?.做兜底,状态为空时不会抛出错误 - 状态更新后组件会自动触发重渲染,不需要额外加定时器监听状态变化
内容的提问来源于stack exchange,提问作者David2203
相关产品推荐
相关产品推荐

