You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中Jotai useEffect触发无限更新深度超限问题排查

问题原因分析

你遇到的「Maximum update depth exceeded」循环问题,核心原因有两点:

  1. Provider嵌套错误:AuthProvider未包裹任何子组件,导致它无法提供上下文,且当auth状态更新时,依赖auth原子的其他Provider(如UserProvider)重新渲染,会触发App组件重复渲染,进而重复创建AuthProvider实例,每次实例化都会新增一个AppState事件监听器。
  2. 重复触发刷新:应用切回前台时,多个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 19:19:48