离线时Firebase初始化报错:默认应用已存在不同配置
Firebase离线场景下初始化重复应用错误的解决方法
问题描述
使用useFireBaseAuth钩子集成Firebase到应用中,联网状态下功能正常,但离线时触发以下错误:
服务器错误
FirebaseError: Firebase: Firebase App named '[DEFAULT]' already exists with different options or config (app/duplicate-app).
怀疑问题出在钩子的Firebase初始化逻辑,初始代码片段:
if (firebaseConfig) { app = initializeApp(firebaseConfig); authInstance = getAuth(app); }
尝试在初始化前通过!app判断避免重复初始化,但错误依然存在:
if (!app) { app = initializeApp(firebaseConfig); authInstance = getAuth(app); }
完整钩子代码:
const useFireBaseAuth = ({ firebaseConfig }: UseFireBaseAuthProps) => { const router = useRouter(); const [authUser, setAuthUser] = useState<auth.User | null>(null); const [loading, setLoading] = useState(true); let app: any; let authInstance: auth.Auth; const toast = useToast(); if (firebaseConfig) { app = initializeApp(firebaseConfig); authInstance = getAuth(app); } const handleLogout = () => { signOut(authInstance).then((res) => { router.push("/"); }); }; const authStateChangeHandler = (authState: any) => { if (!authState) { setAuthUser(null); setLoading(false); } else { setAuthUser(authState); setLoading(false); } }; useEffect(() => { const unsubscribe = authInstance.onAuthStateChanged(authStateChangeHandler); return () => { unsubscribe(); }; }, []); return { user: authUser, loading, logOut: handleLogout, }; };
解决方案
问题核心
- 钩子内的
app和authInstance是局部变量,每次组件渲染都会重新声明,导致!app判断完全无效——每次渲染时app都是新的undefined,会重复执行初始化。 - 离线时组件可能因状态变化(如
loading、authUser)触发重渲染,反复执行初始化代码,而Firebase不允许重复初始化同名应用。
修正后的代码
const useFireBaseAuth = ({ firebaseConfig }: UseFireBaseAuthProps) => { const router = useRouter(); const [authUser, setAuthUser] = useState<auth.User | null>(null); const [loading, setLoading] = useState(true); const [authInstance, setAuthInstance] = useState<auth.Auth | null>(null); const toast = useToast(); // 仅在首次渲染或配置变化时执行Firebase初始化 useEffect(() => { if (!firebaseConfig) return; // 检查是否已存在DEFAULT应用 const existingApp = getApps().find(app => app.name === '[DEFAULT]'); const app = existingApp || initializeApp(firebaseConfig); const auth = getAuth(app); setAuthInstance(auth); }, [firebaseConfig]); // 确保auth实例存在后,再绑定状态监听 useEffect(() => { if (!authInstance) return; const unsubscribe = authInstance.onAuthStateChanged((authState) => { setAuthUser(authState); setLoading(false); }); return () => unsubscribe(); }, [authInstance]); const handleLogout = () => { if (!authInstance) return; signOut(authInstance).then(() => { router.push("/"); }); }; return { user: authUser, loading, logOut: handleLogout, }; };
关键改进点
- 使用Firebase官方的
getApps()方法检查已初始化的应用,彻底避免重复创建。 - 将初始化逻辑放入
useEffect,依赖firebaseConfig确保仅在必要时执行。 - 用
useState保存authInstance,保证跨渲染周期的实例一致性。 - 拆分状态监听的
useEffect,依赖authInstance确保实例存在后再执行,避免空指针错误。 - 在
handleLogout中增加实例存在判断,防止离线时调用无效实例。
内容的提问来源于stack exchange,提问作者Farhan
相关产品推荐
相关产品推荐

