React Native异步调用后状态更新数据错误问题排查
问题定位与解决方案
核心问题:竞态条件 + 未取消异步请求
快速切换标签页时,多次触发useFocusEffect会启动多个并行的异步请求。如果前一次页面失去焦点后,未完成的请求没有被取消,当它最终返回结果时,会覆盖当前页面的状态。若旧请求的响应晚于新请求,就可能出现tipPostList被错误赋值的情况。
解决步骤
1. 添加请求取消机制(推荐)
使用AbortController(axios v0.22.0+ 推荐)或CancelToken(已废弃),在页面失去焦点时取消未完成的请求,避免旧请求覆盖新状态。
修改CommunityPage.jsx:
const [tipPostList, setTipPostList] = useState([]); const [freePostList, setFreePostList] = useState([]); useFocusEffect( useCallback(() => { const controller = new AbortController(); const fetchPosts = async () => { try { const [responseTip, responseFree] = await Promise.all([ getPostsByType("TIP", controller.signal), getPostsByType("FREE", controller.signal), ]); setTipPostList(responseTip.data.slice(0, 3)); setFreePostList(responseFree.data.slice(0, 3)); } catch (error) { // 忽略请求取消的错误 if (error.name !== "AbortError") { Sentry.captureException(error); } } }; fetchPosts(); // 页面失去焦点时取消请求 return () => controller.abort(); }, []), );
修改api.js:
export const getPostsByType = (type, signal) => { return api.get("/posts", { params: { type }, signal: signal }); };
2. 排查axios缓存配置
如果你的axios实例配置了缓存(如axios-cache-adapter),需确保缓存Key包含type参数。若缓存逻辑仅依据URL生成Key,会导致TIP和FREE请求共用同一缓存结果,引发状态赋值错误。
3. 验证请求返回数据
在前端添加日志,确认请求返回的responseTip和responseFree是否对应正确的类型,彻底排除后端返回数据的问题:
const [responseTip, responseFree] = await Promise.all([ getPostsByType("TIP", controller.signal).then(res => { console.log("TIP请求返回:", res.data); return res; }), getPostsByType("FREE", controller.signal).then(res => { console.log("FREE请求返回:", res.data); return res; }), ]);
内容的提问来源于stack exchange,提问作者Seungho Lee
相关产品推荐
相关产品推荐

