繁体   English   中英

为什么“用户”在 onAuthStateChanged(Firebase 9 + Vue 3 + Pinia)中总是“空”?

[英]Why 'user' is always 'null' in onAuthStateChanged (Firebase 9 + Vue 3 + Pinia)?

我对 Firebase 的onAuthStateChanged有问题,无论我尝试了什么,在页面重新加载后总是将user返回为null 所需的行为是在页面重新加载后自动登录用户。

那是我第一次使用模块化版本的 Firebase 9 和 Pinia 作为商店。

我已经尝试使用setPersistence (LOCAL) 但结果是一样的。

我被困了一整天,无法弄清楚为什么它不起作用。

如果能指出我在那里遗漏的内容,我将不胜感激。

我在package.json中使用的包:

"dependencies": {
    "firebase": "^9.6.11",
    "pinia": "^2.0.13",
    "vue": "^3.2.13",
    "vue-router": "^4.0.3"
  }

main.ts文件:

import { createApp, App as VueApp } from 'vue';
import { createPinia } from 'pinia';
import { auth } from '@/firebase';
import { onAuthStateChanged, User } from 'firebase/auth';
import { useAuthStore } from '@/store/auth';

let app: VueApp;

function initializeApp(user: User | null) {
  app = createApp(App)
    .use(createPinia())
    .use(router);

  if (user) {
    // PROMEM IS THERE -> user IS ALWAYS null
    // I want to set logged user before app is mounted
    const authStore = useAuthStore();
    authStore.handleAuthStateChange(user);
  }

  app.mount('#app');
}

onAuthStateChanged(
  auth,
  (user: User | null) => {
    // PROMEM IS THERE -> user IS ALWAYS null
    if (!app) {
      initializeApp(user);
    } else {
      const authStore = useAuthStore();
      authStore.handleAuthStateChange(user);
    }
  },
  (error: Error) => {
    log.error(`Main AuthStateChange handler failed with error`, error);
  },
);

firebase.ts文件:

import { FirebaseApp, initializeApp } from 'firebase/app';
import { Auth, initializeAuth, debugErrorMap } from 'firebase/auth';
import { firebaseConfig } from '@/config';

export const app: FirebaseApp = initializeApp(firebaseConfig);
export const auth: Auth = initializeAuth(app, { errorMap: debugErrorMap });

auth.ts -> 存储文件:

import { defineStore } from 'pinia';
import { LoginCredentials, SignUpCredentials } from '@/types/auth';
import { FirebaseAuthenticationService, AuthenticationService } from '@/service/AuthenticationService';
import { auth as firebaseAuth } from '@/firebase';
import { log } from '@/service/LoggerService';

export interface AuthStoreUser {
  uid: string,
  email: string | null
}

export type MaybeAuthStoreUser = AuthStoreUser | null;

export interface AuthStoreState {
  user: AuthStoreUser | null,
}

export const authStoreFactory = ($auth: AuthenticationService) => defineStore('auth', {
  state: () => ({
    user: null,
  } as AuthStoreState),
  getters: {
    isUserLoggedIn(): boolean {
      return !!this.user;
    },
  },
  actions: {
    async signUpUser(credentials: SignUpCredentials) {
      const createdUser = await $auth.createUserWithEmailAndPassword(credentials);
    },
    async loginUser(credentials: LoginCredentials) {
      const user = await $auth.signInWithEmailAndPassword(credentials);
    },
    async setCurrentUser(user: AuthStoreUser) {
      this.user = user;
    },
    async clearCurrentUser() {
      this.user = null;
    },
    async logoutUser() {
      await $auth.signOut();
    },
    async sendPasswordResetEmail(email: string) {
      await $auth.sendPasswordResetEmail(email);
    },
    async handleAuthStateChange(user: MaybeAuthStoreUser) {
      if (user) {
        log.debug(`Logging in user from authStateChange handler`);
        this.setCurrentUser(user);
      } else {
        log.debug(`AuthStateChange handler did not receive current user.`);
        this.clearCurrentUser();
      }
    },
  },
});

export const useAuthStore = () => {
  const $auth = new FirebaseAuthenticationService(firebaseAuth);
  return authStoreFactory($auth)();
};

我终于通过向initializeAuth添加persistence选项解决了这个问题。 这部分的文档具有误导性,没有正确解释应该如何使用initializeAuth方法完成...

这是auth应该如何在firebase.ts文件中初始化:

import { firebaseConfig } from '@/config';
import { FirebaseApp, initializeApp } from 'firebase/app';
import { 
  Auth, 
  initializeAuth, 
  debugErrorMap,
  indexedDBLocalPersistence, 
  browserLocalPersistence } from 'firebase/auth';

export const app: FirebaseApp = initializeApp(firebaseConfig);
export const auth: Auth = initializeAuth(app, { 
  persistence: [indexedDBLocalPersistence, browserLocalPersistence],
  errorMap: debugErrorMap 
});

我在文档中发现的内容很有趣:

web 浏览器和 React Native 应用程序的默认设置是本地的(前提是浏览器支持此存储机制,例如启用了第 3 方 cookie/数据),而 Node.js 后端应用程序则没有。

这是我在auth-public.d.ts文件中找到的:

export declare interface Dependencies {
    /**
     * Which {@link Persistence} to use. If this is an array, the first
     * `Persistence` that the device supports is used. The SDK searches for an
     * existing account in order and, if one is found in a secondary
     * `Persistence`, the account is moved to the primary `Persistence`.
     *
     * If no persistence is provided, the SDK falls back on
     * {@link inMemoryPersistence}.
     */
    persistence?: Persistence | Persistence[];
    // other stuff
}

如果未提供持久性,则 SDK 返回到 inMemoryPersistence

inMemoryPersistence意味着NONE持久化。 这就是我的问题的原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM