React Native中Jotai useEffect触发无限更新深度超限问题排查
问题原因分析
你遇到的「Maximum update depth exceeded」循环问题,核心原因有两点:
- Provider嵌套错误:AuthProvider未包裹任何子组件,导致它无法提供上下文,且当auth状态更新时,依赖auth原子的其他Provider(如UserProvider)重新渲染,会触发App组件重复渲染,进而重复创建AuthProvider实例,每次实例化都会新增一个AppState事件监听器。
- 重复触发刷新:应用切回前台时,多个AppState监听器同时触发,调用
refreshAuth()更新auth原子,再次触发组件渲染,形成无限循环。
解决方案
1. 修复Provider嵌套结构
将所有依赖Auth状态的组件/Provider包裹在AuthProvider内部,确保AuthProvider仅实例化一次,且上下文能正确传递:
// App组件修改后的嵌套结构 <Suspense fallback={<CenteredActivityIndicator />}> <AuthProvider> {/* 包裹所有依赖Auth的组件 */} <UserProvider> <InitProvider> <ScrollProvider> <RootFlashMessageProvider> <RootStack /> </RootFlashMessageProvider> </ScrollProvider> </InitProvider> </UserProvider> </AuthProvider> </Suspense>
2. 确保依赖项稳定,避免重复添加监听器
在useLogin hook中用useCallback包裹logout函数,保证其引用稳定,防止useEffect因依赖变化重复执行:
// use-login.hook.js import { useCallback } from 'react' export const useLogin = () => { // ...原有逻辑 const logout = useCallback(() => { // 你的logout实现代码 }, [/* 此处添加logout依赖的变量 */]) return { logout } }
3. 添加刷新锁,防止并发调用
在AuthProvider中添加引用锁,避免refreshAuth()异步执行期间重复触发刷新:
// AuthProvider组件修改 export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => { const refreshAuth = useSetAtom(refreshAuthAtom) const { logout } = useLogin() const appState = useRef(AppState.currentState) const isRefreshing = useRef(false) // 新增刷新锁 useEffect(() => { const subscription = AppState.addEventListener( 'change', async (nextState) => { const previousStateIsBackgroundOrInactive = appState.current.match(/inactive|background/) // 仅当未在刷新时执行 if (previousStateIsBackgroundOrInactive && nextState === 'active' && !isRefreshing.current) { isRefreshing.current = true try { await refreshAuth() console.log('AUTH REFRESHED') } catch (e) { console.log('error refreshing auth: ', e) logout() } finally { isRefreshing.current = false // 释放锁 } } appState.current = nextState } ) return () => { subscription.remove() } }, [refreshAuth, logout]) return ( <PasswordAuthContext.Provider value={{}}> {children} {/* 现在正确传递子组件 */} </PasswordAuthContext.Provider> ) }
4. 验证原子定义稳定性
确保refreshAuthAtom在模块级别定义(当前代码已满足),避免在组件内部重复创建原子,导致状态管理混乱。
内容的提问来源于stack exchange,提问作者11Korvar
相关产品推荐
相关产品推荐

