无法在加载时获得currentUser

时间:2016-06-17 14:20:54

标签: javascript firebase firebase-authentication

尝试检查用户是否通过firebase.auth().currentUser登录时是这样的:

if (firebase.auth().currentUser === null) {
  console.log('User not signed in');
}

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

奇怪的是,如果我记录

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

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

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

9 个答案:

答案 0 :(得分:26)

这是一个常见问题。 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.
  }
});

答案 1 :(得分:5)

始终有权访问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);
    }
});

以上唯一的问题是,如果用户在浏览器上按刷新,则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();
    }
  }
})

您现在可以按照以下代码示例保护路由器中的路由。

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()
    }
})

答案 2 :(得分:4)

一种简单的方法是添加未决状态。

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

// useAuth.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 }
}

// SignIn.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>
  )
}

答案 3 :(得分:0)

  // On component load.
  componentDidMount = () => this.getAuthStatus();

  // Get firebase auth status.
  getAuthStatus = () => {
    firebase.auth().onAuthStateChanged((resp) => {

        // Pass response to a call back func to update state
        this.updateUserState(resp);
    });
  }

  // update state
  updateUserState = (resp) => {
     this.setState({
         user: resp
     })
  }

  // Now you can validate anywhere within the component status of a user
  if (this.state.user) { /*logged in*/}

答案 4 :(得分:0)

如果您正在寻找复制和粘贴Auth路由以与Firebase反应:

const AuthRoute = ({ component: Component, ...rest }) => {
      const [authenticated, setAuthenticated] = useState(false)
      const [loadingAuth, setLoadingAuth] = useState(true)

      useEffect(() => {
        firebase.auth().onAuthStateChanged((user) => {
          if (user) {
            setAuthenticated(true)
          } else {
            setAuthenticated(false)
          }
          setLoadingAuth(false)
        })
      }, [])
      return loadingAuth ? 'loading...' : (
        <Route
          {...rest}
          render={props =>
            authenticated ? (
              <Component {...props} />
            ) : (
              <Redirect to={{ pathname: '/user/login' }} />
            )}
        />

      )
    }

答案 5 :(得分:0)

最好的方法是使用promise,并且仅在响应后实例化路由器,类似于:

store.dispatch('userModule/checkAuth').then(() => {
  // whatever code you use to first initialise your router, add it in here, for example
  new Vue({
    router,
    store,
    render: h => h(App)
  }).$mount('#app')
})

在checkAuth动作中是您的诺言,例如:

checkAuth ({ commit }) {
return new Promise((resolve, reject) => {
  firebase.auth().onAuthStateChanged(async (_user) => {
    if (_user) {
      commit('setUser', _user)
    } else {
      commit('setUser', null)
    }
    console.log('current user in checkAuth action:', _user)
    resolve(true)
  })
})

h / t转换为aaron k saunders-对我而言,此解决方案的来源。

答案 6 :(得分:0)

Promise-wise,有三个选项:

// best option

const user1 = await new Promise((resolve: any, reject: any) =>
firebase.auth().onAuthStateChanged((user: any) =>
  resolve(user), (e: any) => reject(e)));

console.log(user1);

// sometimes does not display correctly when logging out

const user2 = await firebase.auth().authState.pipe(first()).toPromise();

console.log(user2);

// technically has a 3rd state of 'unknown' before login state is checked

const user3 = await firebase.auth().currentUser;

console.log(user3);

答案 7 :(得分:-1)

`Import-Module PSFTP`
`$FTPServer = 'domain.com'`
`$FTPUsername = 'username'`
`$FTPPassword = 'password'`
`$FTPSecurePassword = ConvertTo-SecureString -String $FTPPassword  -asPlainText -Force`
`$FTPCredential = New-Object      System.Management.Automation.PSCredential($FTPUsername,$FTPSecurePassword)`

`Set-FTPConnection -Credentials $FTPCredential -Server $FTPServer -Session MySession -UsePassive`

`$Session = Get-FTPConnection -Session MySession`

`$output = Get-FTPChildItem   -Session $Session  -Path '/'   | Select ModifiedDate, Name |  Where-Object {($_.ModifiedDate -lt (Get-Date).AddDays(-7))}|select name `

`echo $output`

foreach ( $file in $output ) {
    Remove-FTPItem  $file.name -Recurse -Session $Session -Verbose
}

首先检查用户是否存在,然后通过

获取它的ID
  

firebase.auth()。currentUser.uid

答案 8 :(得分:-9)

这很容易解决!!! 您可以使用firebase.js的最新版本,例如在您的firebase网络设置中找到它。.

 <script src="https://www.gstatic.com/firebasejs/5.4.2/firebase.js"> . </script> 

希望它会解决!