无法在加载时获得currentUser

Chr*_*ris 31 javascript firebase firebase-authentication

尝试检查用户是否通过firebase.auth().currentUser以下方式登录时:

if (firebase.auth().currentUser === null) {
  console.log('User not signed in');
}
Run Code Online (Sandbox Code Playgroud)

每当我刷新页面,或在上面导航时返回null(即使我刚刚登录).

奇怪的是,如果我登录

console.log(firebase.auth().currentUser) // This returns null
console.log(firebase.auth()) // Here I can inspect the object and currentUser exists...!
Run Code Online (Sandbox Code Playgroud)

我真的不知道这里发生了什么.我正在使用React和Redux,但我说的并不重要.

firebase初始化时是否存在小延迟,您无法访问currentUser?如果是这样,我如何在日志输出中看到它firebase.auth()

boj*_*eil 33

这是一个常见问题. https://firebase.google.com/docs/auth/web/manage-users 您需要向onAuthStateChanged添加一个观察者来检测初始状态和所有后续状态更改,

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
  } else {
    // No user is signed in.
  }
});
Run Code Online (Sandbox Code Playgroud)

  • 实际上,当初始状态确定时,这将始终触发.之后,当auth状态发生变化时,它将触发.这是检测初始身份验证状态的推荐方法.您可以在确定初始状态后将其删除.var unsubscribe = auth1.onAuthStateChanged(function(user){//执行init stuff然后取消订阅;取消订阅();}); (8认同)
  • 这是为了获得有关身份验证状态更改的通知,它没有为我提供检查用户是否在任何给定时间进行身份验证的方法 (6认同)
  • 我仍然觉得很奇怪,在第一个 console.log 上,对象如何与当前用户密钥一起存在,而在第二个 console.log 上,您无法访问该密钥。看起来,第一次执行 console.log 时,该对象可供浏览器使用,那么为什么它不允许从该对象中选择任何内容呢? (5认同)

Pre*_*cks 8

始终访问 currentUser 的最佳方法是使用 vuex 和vuex-persistedstate

//Configure firebase
firebase.initializeApp(firebaseConfig);
//When ever the user authentication state changes write the user to vuex.
firebase.auth().onAuthStateChanged((user) =>{
    if(user){
        store.dispatch('setUser', user);
    }else{
        store.dispatch('setUser', null);
    }
});
Run Code Online (Sandbox Code Playgroud)

上面唯一的问题是,如果用户在浏览器上按下刷新,vuex 状态将被丢弃,您必须等待 onAuthStateChange 再次触发,因此当您尝试访问 currentUser 时为什么会得到 null。

上述代码一直工作的秘诀是使用 vuex 持久化状态。

在您的 store.js 文件中

import Vue from 'vue'
import Vuex from 'vuex'
import firebase from 'firebase/app'
Vue.use(Vuex)
import createPersistedState from "vuex-persistedstate";
export default new Vuex.Store({
    plugins: [createPersistedState()],
  state: {
    user: null
  },
    getters:{
      getUser: state => {
          return state.user;
      }
    },
  mutations: {
    setUser(state, user){
      state.user = user;
    }
  },
  actions: {
    setUser(context, user){
        context.commit('setUser', user);
    },
    signIn(){
        let provider = new firebase.auth.GoogleAuthProvider();
        firebase.auth().signInWithPopup(provider).then(function (result) {
      })
    },
    signOut(){
        firebase.auth().signOut();
    }
  }
})
Run Code Online (Sandbox Code Playgroud)

您现在可以保护路由器中的路由,如下面的代码示例所示。

import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import Search from '@/components/Search/Search'
import CreateFishingSite from '@/components/FishingSites/CreateFishingSite'
Vue.use(Router);
import store from './store'
import firebase from 'firebase'

let router = new Router({
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
      {
          path: '/search/:type',
          name: 'Search',
          component: Search
      },
      {
          path: '/fishingsite/create',
          name: 'CreateFishingSite',
          component: CreateFishingSite,
          meta: {
              requiresAuth: true
          }
      }

  ]
})

router.beforeEach(async (to, from, next)=>{
    let currentUser = store.state.user;
    console.log(currentUser);
    let requriesAuth = to.matched.some(record => record.meta.requiresAuth);
    if(requriesAuth && !currentUser){
        await store.dispatch('signIn');
        next('/')
    }else{
        next()
    }
})
Run Code Online (Sandbox Code Playgroud)


小智 7

一个简单的方法是添加一个挂起状态。

这是一个使用钩子的反应示例:

// 使用Auth.ts

import { useState, useEffect } from 'react'
import { auth } from 'firebase'

export function useAuth() {
  const [authState, setAuthState] = useState({
    isSignedIn: false,
    pending: true,
    user: null,
  })

  useEffect(() => {
    const unregisterAuthObserver = auth().onAuthStateChanged(user =>
      setAuthState({ user, pending: false, isSignedIn: !!user })
    )
    return () => unregisterAuthObserver()
  }, [])

  return { auth, ...authState }
}
Run Code Online (Sandbox Code Playgroud)

// 登录.tsx

import React from 'react'
import { StyledFirebaseAuth } from 'react-firebaseui'
import { useAuth } from '../hooks'

export default function SignIn() {
  const { pending, isSignedIn, user, auth } = useAuth()

  const uiConfig = {
    signInFlow: 'popup',
    signInOptions: [
      auth.GoogleAuthProvider.PROVIDER_ID,
      auth.FacebookAuthProvider.PROVIDER_ID,
    ],
  }

  if (pending) {
    return <h1>waiting...</h1>
  }

  if (!isSignedIn) {
    return (
      <div>
        <h1>My App</h1>
        <p>Please sign-in:</p>
        <StyledFirebaseAuth uiConfig={uiConfig} firebaseAuth={auth()} />
      </div>
    )
  }

  return (
    <div>
      <h1>My App</h1>
      <p>Welcome {user.displayName}! You are now signed-in!</p>
      <a onClick={() => auth().signOut()}>Sign-out</a>
    </div>
  )
}

Run Code Online (Sandbox Code Playgroud)