React报错:Maximum update depth exceeded问题求助(附代码)
解决React中'Maximum update depth exceeded'错误(Socket.io通信场景)
问题根源
你遇到的无限循环更新问题,核心原因是第二个useEffect的依赖配置错误:
- 该
useEffect依赖UIoutputs,每次UIoutputs状态更新时,都会重新执行钩子并给Socket注册新的UIoutputs事件监听器。 - 当服务器推送数据时,监听器触发
setUIoutputs更新状态,状态变化又会再次触发useEffect执行,形成无限循环,最终触发更新深度超限错误。 - 重复注册的监听器还会导致同一数据多次触发状态更新,进一步加剧问题。
修复后的代码
const address = "http://localhost:4010" const socket = io(address); function App() { const [MenuState, setMenuState] = useState("/") const [UIinputs, setUIinputs] = useState({ progressState: "stop" }); const [UIoutputs, setUIoutputs] = useState({ deliveredEnergy: 0, estTime: "00:00:00", estCost: 0, soc: 75, chargerState: 4, currentPower: 0, progressState: 2, current: 0, voltage: 5, carID: "a", debug: [{}, {}] }); useEffect(() => { socket.emit('UIinputs', UIinputs) }, [UIinputs]) useEffect(() => { // 独立定义事件处理函数,方便后续移除监听 const handleUIOutputs = (data) => { setUIoutputs(prevState => ({ ...prevState, deliveredEnergy: data.deliveredEnergy, estTime: data.estTime, soc: data.soc, chargerState: data.chargerState, currentPower: data.currentPower, progressState: data.progressState, current: data.current, carID: data.carID, voltage: data.voltage, debug: data.debug, })); }; // 仅在组件挂载时注册一次事件监听 socket.on('UIoutputs', handleUIOutputs); // 组件卸载时移除监听,避免内存泄漏 return () => { socket.off('UIoutputs', handleUIOutputs); }; }, []) // 空依赖数组,确保钩子只执行一次 return ( <React.Fragment> <CssBaseline /> <div className='app-container'> <div className='top-bar'> <Header /> <BackButton MenuState={MenuState} setMenuState={setMenuState} /> <ScanQR /> </div> <Routes> <Route path='/' element={ <Menu UIoutputs={UIoutputs} setMenuState={setMenuState} />}> </Route> <Route path='/profile' element={ <Profile UIoutputs={UIoutputs} />}> </Route> <Route path="/station" element={ <Charger UIinputs={UIinputs} setUIinputs={setUIinputs} UIoutputs={UIoutputs} setUIoutputs={setUIoutputs} />}> </Route> <Route path="/dev" element={ <Dev UIoutputs={UIoutputs} />}> </Route> </Routes> <BottomBar /> </div> </React.Fragment> ); };
关键修改说明
- 移除不必要的依赖:第二个
useEffect使用空依赖数组[],确保事件监听只在组件挂载时注册一次,不会重复绑定。 - 函数式状态更新:使用
setUIoutputs(prevState => ...)的形式更新状态,无需依赖当前UIoutputs值,避免了依赖项的冗余添加。 - 清理事件监听:添加返回函数在组件卸载时移除Socket事件监听,防止内存泄漏。
内容的提问来源于stack exchange,提问作者Alperen Yılma
相关产品推荐
相关产品推荐

