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

Firebase auth().onAuthStateChanged未等待signInWithCredential完成如何解决

问题核心原因

onAuthStateChanged 是Firebase Auth SDK的内置状态监听,只要用户认证凭证校验通过(即signInWithCredential执行成功)就会立刻触发,和后续Firestore的读写操作完全独立,无法直接延迟它的触发时机,你遇到的是典型的Auth层和数据层操作的竞态问题。

解决方案

方案1(推荐):登录流程全完成后再跳转首页

从根源避免首页提前加载触发监听,把登录页的异步回调嵌套改为async/await写法,确保老用户校验、新用户数据写入全部执行完成后,再执行路由跳转进入首页。
修改后的登录页代码:

const _signIn = async () => {
  setInitializing(true);
  try {
    await GoogleSignin.hasPlayServices();
    const userInfo = await GoogleSignin.signIn();
    const credential = auth.GoogleAuthProvider.credential(
      userInfo.idToken,
      userInfo.accessToken,
    );
    // 完成认证
    const response = await auth().signInWithCredential(credential);
    const uid = response.user.uid;
    const usersRef = firestore().collection('users');
    const firestoreDocument = await usersRef.doc(uid).get();
    // 新用户写入数据
    if (!firestoreDocument.exists) {
      const data = {
        uid: uid,
        email: userInfo.user.email,
        fullname: userInfo.user.name,
        bio: 'Halo!! ..',
        username: uid.substring(0, 8),
      };
      await usersRef.doc(data.uid).set(data);
    }
    // 所有操作完成再跳转首页,此时首页监听触发时数据已存在
    setInitializing(false);
    navigation.navigate('Home'); // 替换为实际的首页路由名
  } catch (error) {
    setInitializing(false);
    if (error.code === statusCodes.SIGN_IN_CANCELLED) {
      Alert.alert('Sign in canceled');
    } else if (error.code === statusCodes.IN_PROGRESS) {
      Alert.alert('Signin in progress');
    } else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
      Alert.alert('PLAY_SERVICES_NOT_AVAILABLE');
    } else {
      Alert.alert(error.message);
    }
  }
};

方案2:优化首页监听逻辑,增加容错等待

如果业务逻辑需要首页提前加载监听认证状态,可以修改首页的监听逻辑,不直接读取不存在的文档数据,改为监听文档快照,等文档写入完成后再执行后续操作。
修改后的首页代码:

useEffect(() => {
  let authUnsubscribe = null;
  const init = async () => {
    try {
      const netState = await NetInfo.fetch();
      if(!netState.isConnected){
        Alert.alert('No Internet Connection Detected');
        setInitializing(false);
        return;
      }
      setInitializing(true);
      // 监听认证状态
      authUnsubscribe = auth().onAuthStateChanged((user) => {
        if (user) {
          const usersRef = firestore().collection('users');
          // 监听文档快照,等待文档存在后再执行后续逻辑
          const docUnsubscribe = usersRef.doc(user.uid).onSnapshot((document) => {
            if (document.exists) {
              const userData = document.data().uid;
              setisLogin(userData);
              setInitializing(false);
              docUnsubscribe(); // 取消文档监听避免内存泄漏
            }
          }, (error) => {
            setInitializing(false);
            Alert.alert(error.message);
            docUnsubscribe();
          });
        } else {
          setInitializing(false);
        }
      });
    } catch (error) {
      setInitializing(false);
      Alert.alert(error.message);
    }
  };
  init();
  // 组件卸载时取消监听避免内存泄漏
  return () => {
    if (authUnsubscribe) authUnsubscribe();
  }
}, []);
注意事项
  • 原首页代码中给onAuthStateChanged加await是无效的,该方法返回的是取消监听的函数,不是Promise,无需加await
  • 所有异步监听方法要在组件卸载时调用取消函数,避免内存泄漏

内容的提问来源于stack exchange,提问作者Mukhlis Saputro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 16:36:02