React表单提交时useEffect重复触发API调用致400错误如何解决
核心问题原因
ShowRoleApp组件的useEffect未将applicationRole加入依赖数组,组件每次挂载都会发起请求,且父组件表单提交触发的重渲染会导致组件重复挂载,进而多次调用接口。- 未添加请求取消逻辑,未完成的请求在响应返回后仍会触发状态更新,进一步引发多余重渲染和重复请求。
GetProfili中不必要的res.clone()调用可能导致响应解析异常,触发额外重渲染。
具体修改方案
1. 修正ShowRoleApp组件的useEffect逻辑
添加正确依赖、请求取消逻辑、组件卸载保护,避免重复请求:
const ShowRoleApp = ({ applicationRole }) => { const [profili, setProfili] = useState([]); const [isLoading, setIsLoading] = useState(false); useEffect(() => { // 没有选中值时直接清空状态返回 if (!applicationRole) { setProfili([]); setIsLoading(false); return; } setIsLoading(true); // 声明abort控制器用于取消请求 const abortController = new AbortController(); let isMounted = true; async function init() { try { const res = await GetProfili(applicationRole, abortController.signal); // 组件未卸载才更新状态 if (isMounted) { setProfili(res); setIsLoading(false); } } catch (err) { // 忽略请求取消的报错 if (err.name !== 'AbortError' && isMounted) { console.log('err ', err); setIsLoading(false); } } } init(); // 清理函数:组件卸载/依赖变化时取消请求,标记组件已卸载 return () => { isMounted = false; abortController.abort(); }; // 把applicationRole加入依赖数组,只有值变化才重新执行effect }, [applicationRole]); if (!applicationRole) { return <div />; } return isLoading ? ( <div className='d-flex justify-content-center'> <div className='spinner-border text-primary' role='status'> <span className='visually-hidden'></span> </div> </div> ) : ( RenderProfili(profili, applicationRole) ); };
2. 优化GetProfili函数
移除多余clone调用,支持传入abort信号:
const GetProfili = async (appCod, signal) => { const chiamata = 'myApi' + appCod.toString(); const res = await fetch(chiamata, { signal }); // 直接调用json()即可,无需clone const result = await res.json(); return result; };
可选优化:添加请求防抖
如果下拉选择时需要避免快速切换选项触发多次请求,可添加防抖逻辑:
// 全局声明防抖函数 const debounce = (func, delay = 300) => { let timeoutId; return (...args) => { clearTimeout(timeoutId); timeoutId = setTimeout(() => func.apply(this, args), delay); }; }; // ShowRoleApp内使用防抖后的请求函数 const fetchProfili = useCallback(debounce(async (appCod, signal) => { // 请求逻辑同上 }), []);
修改后只有当applicationRole的值发生变化时才会发起新请求,提交表单时的重渲染不会再触发重复调用,400错误也会随之解决。
内容的提问来源于stack exchange,提问作者Jack23
相关产品推荐
相关产品推荐

