useEffect中前一次异步请求覆盖当前状态更新的问题求助
解决异步请求覆盖状态的问题
问题核心是异步请求的滞后性:当q快速变化时,前一次的fetchSomething请求还未完成,后一次已经执行了setStuff([]),等旧请求返回后会覆盖掉空数组。
方案1:使用AbortController取消旧请求
利用浏览器原生的AbortController,每次useEffect执行时取消上一次未完成的请求,确保只有当前q对应的请求能触发状态更新:
useEffect(() => { const controller = new AbortController(); const signal = controller.signal; if (q.length > 2) { fetchSomething(q, { signal }).then(thing => { setStuff(thing); }).catch(err => { // 忽略取消请求导致的错误 if (err.name !== 'AbortError') throw err; }); } else { setStuff([]); } // 组件卸载或q变化时,取消当前请求 return () => controller.abort(); }, [q]);
注意:需要确保fetchSomething支持接收signal参数并传递给底层的fetch或axios(axios可使用新版的AbortController或旧版cancelToken)。
方案2:校验当前q与请求时的q一致
在异步回调中检查当前的q是否和发起请求时的q相同,只有一致时才更新状态:
useEffect(() => { const currentQuery = q; if (currentQuery.length > 2) { fetchSomething(currentQuery).then(thing => { // 只有当前q和发起请求时的q一致,才更新状态 if (q === currentQuery) { setStuff(thing); } }); } else { setStuff([]); } }, [q]);
这个方案不需要修改fetchSomething,但无法取消旧请求,可能会造成不必要的网络请求。
内容的提问来源于stack exchange,提问作者jjyj
相关产品推荐
相关产品推荐

