React中两个Ant Design滑块操作时同时触发双请求问题排查
错误定位
两个滑块的请求逻辑共用了同一个ok状态作为useEffect的触发依赖,是问题的核心原因:
- 无论操作哪个滑块,最后都会执行
setOk(!ok)修改公共状态 - 两个请求对应的useEffect都把
[ok]设为依赖数组,只要ok变化,两个effect会同时执行,自然会同时输出两条请求日志、发起两次请求 - 现有写法还存在闭包风险:useEffect依赖中没有包含实际使用的
load/freq状态,极端场景下会拿到过期的旧状态值发起错误请求 - 用翻转公共布尔值+setTimeout的触发方式本身就存在逻辑串扰问题,只要有多个逻辑绑定同一个触发标记,就会出现联动执行的问题
修复方法
移除公共的ok触发状态,让每个滑块的请求逻辑只监听自己对应的状态变化即可:
- 调整状态定义,删除多余的公共
ok状态
const [load, setLoad] = useState([0, 16]); const [freq, setFreq] = useState([0, 28]);
- 重写两个滑块对应的useEffect,分别监听自己的状态,移除对公共
ok的依赖
// 滑块1(承载力)对应请求 useEffect(() => { console.log("ok to request load"); fetchProducts({ load }); }, [load]); // 滑块2(固有频率)对应请求 useEffect(() => { console.log("ok to request freq"); fetchProducts({ freq }); }, [freq]);
- 简化滑块变更回调,去掉多余的setTimeout和setOk逻辑
// 滑块1变更回调 const handleSliderLoad = (valueLoad) => { setLoad(valueLoad); }; // 滑块2变更回调 const handleSliderFreq = (valueFreq) => { setFreq(valueFreq); };
如果需要保留300ms延迟触发、避免拖动滑块过程中频繁发请求的逻辑,给每个滑块单独定义防抖定时器即可,不要共用触发标记:
// 滑块1防抖示例 const loadTimer = useRef(null); const handleSliderLoad = (valueLoad) => { setLoad(valueLoad); clearTimeout(loadTimer.current); loadTimer.current = setTimeout(() => { fetchProducts({ load: valueLoad }); }, 300); }; // 滑块2防抖示例 const freqTimer = useRef(null); const handleSliderFreq = (valueFreq) => { setFreq(valueFreq); clearTimeout(freqTimer.current); freqTimer.current = setTimeout(() => { fetchProducts({ freq: valueFreq }); }, 300); };
注意:用防抖写法的时候,要把之前useEffect里的fetchProducts调用删掉,避免重复请求。
内容的提问来源于stack exchange,提问作者wil_ap
相关产品推荐
相关产品推荐

