React求助:调用history.push后触发Maximum update depth exceeded无限循环错误
解决React无限循环(Maximum update depth exceeded)问题
问题根源
你的代码触发无限循环的核心逻辑链:
DemoPortalPage挂载时,空依赖的useEffect执行认证逻辑,调用setIsUserVerified更新全局/父组件状态setIsUserVerified触发App组件重新渲染,而history.push("/")的路由跳转是异步操作,跳转完成前DemoPortalPage并未立即卸载- 组件重新渲染后,
useEffect再次执行,重复触发认证、状态更新和路由跳转,形成无限循环
具体解决方案
方案1:添加执行标记,阻止重复触发
用useRef创建一个一次性标记,确保认证逻辑只执行一次:
// DemoPortalPage.jsx import { useEffect, useRef } from 'react'; useEffect(() => { const isAuthExecuted = useRef(false); const authenticateDemoUser = async () => { if (isAuthExecuted.current) return; isAuthExecuted.current = true; const authData = { email: 'demo@gmail.com', password: '1234', }; const checkUserAuth = await postRequest("authenticate", authData); if (checkUserAuth?.status >= 200 && checkUserAuth?.status < 300) { await signInSuccess(checkUserAuth.data); await getAndSaveUserName(); await setIsUserVerified(true); // localStorage.setItem('is_demo', "true") } else { await setIsUserVerified(false); } history.push("/"); } authenticateDemoUser() }, [])
方案2:调整操作顺序+组件卸载清理
将路由跳转放在状态更新之后,同时添加清理函数避免异步操作残留:
// DemoPortalPage.jsx useEffect(() => { const abortCtrl = new AbortController(); const authenticateDemoUser = async () => { try { const authData = { email: 'demo@gmail.com', password: '1234', }; // 传递取消信号,支持中断请求 const checkUserAuth = await postRequest("authenticate", authData, { signal: abortCtrl.signal }); if (checkUserAuth?.status >= 200 && checkUserAuth?.status < 300) { await signInSuccess(checkUserAuth.data); await getAndSaveUserName(); await setIsUserVerified(true); } else { await setIsUserVerified(false); } history.push("/"); } catch (err) { // 忽略取消错误,处理其他异常 if (err.name !== 'AbortError') { await setIsUserVerified(false); history.push("/"); } } } authenticateDemoUser(); // 组件卸载时中断异步请求,避免后续状态更新 return () => abortCtrl.abort(); }, [])
额外检查点
- 确认
/路由对应的组件不会因isUserVerified状态变化,再次跳转到/demo-login,这会引发二次循环 - 检查
signInSuccess、getAndSaveUserName内部是否有隐藏的状态更新或路由跳转逻辑,可能也是循环诱因
内容的提问来源于stack exchange,提问作者Krinal
相关产品推荐
相关产品推荐

