首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么在onAuthStateChanged (Firebase 9+ Vue 3+ Pinia)中'user‘总是'null’?

为什么在onAuthStateChanged (Firebase 9+ Vue 3+ Pinia)中'user‘总是'null’?
EN

Stack Overflow用户
提问于 2022-04-23 12:48:07
回答 1查看 437关注 0票数 1

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

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

我已经尝试过使用setPersistence (本地),但是结果是一样的。

我被困了一整天,弄不明白为什么不起作用。

我很感激能指出我在那里错过了什么。

我在package.json中使用的软件包

代码语言:javascript
运行
复制
"dependencies": {
    "firebase": "^9.6.11",
    "pinia": "^2.0.13",
    "vue": "^3.2.13",
    "vue-router": "^4.0.3"
  }

main.ts文件:

代码语言:javascript
运行
复制
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文件:

代码语言:javascript
运行
复制
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 ->存储文件:

代码语言:javascript
运行
复制
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)();
};
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-23 15:53:44

通过向persistence添加initializeAuth选项,我终于解决了这个问题。对于这一部分,文档是误导性的,没有正确地解释如何用initializeAuth方法来实现。

这就是如何在auth文件中初始化firebase.ts

代码语言:javascript
运行
复制
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 
});

我在文档中发现的东西很有趣

默认的网页浏览器和反应本地应用程序是本地(只要浏览器支持这种存储机制,例如。第三方cookie/数据已启用),而Node.js后端应用程序则不启用。

这就是我在auth-public.d.ts文件中发现的:

代码语言:javascript
运行
复制
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持久化。那是我问题的原因。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71979761

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档