javascript 无法在加载时获取currentUser

webghufk  于 2022-11-27  发布在  Java
关注(0)|答案(9)|浏览(146)

尝试检查用户是否通过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()的日志输出中看到它?

9w11ddsr

9w11ddsr1#

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

unguejic2#

一个简单的方法是添加挂起状态。
下面是一个使用钩子的react示例:
//使用验证

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

//登录.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>
  )
}
1cosmwyk

1cosmwyk3#

始终访问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()
    }
})
w7t8yxp5

w7t8yxp54#

就承诺而言,有三种选择:

更新日期:2022年11月26日

对于Firebase 9+,您可以执行以下操作:

注意:(this.auth)是Auth对象,具体取决于您得框架.

第一个

x6yk4ghg

x6yk4ghg5#

如果您正在寻找一个复制和粘贴Auth路由,以与firebaseReact:

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' }} />
            )}
        />

      )
    }
zqdjd7g9

zqdjd7g96#

// 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*/}
ru9i0ody

ru9i0ody7#

最好的方法是使用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给亚伦k桑德斯-为我这个解决方案的来源。

b09cbbtk

b09cbbtk8#

如果您希望用户仅在通过身份验证后才能访问某个页面,而在未通过身份验证时重定向到主页,则以下代码可能会有所帮助:
在React中:使用以下代码创建一个组件:

import { onAuthStateChanged } from "@firebase/auth";
import { Route, Redirect } from "react-router-dom";
import { auth } from "../firebase/config";
import { useState, useEffect } from "react";

const GuardedRoute = ({ component, path }) => {
  const [authenticated, setAuthenticated] = useState(false);
  const [authCompleted, setAuthCompleted] = useState(false);
  useEffect(() => {
    onAuthStateChanged(auth, (user) => {
      if (user) {
        setAuthenticated(true);
      } else {
        setAuthenticated(false);
      }
      setAuthCompleted(true);
    });
  }, []);
  return authCompleted ? (
    authenticated ? (
      <Route path={path} component={component} />
    ) : (
      <Redirect to="/" />
    )
  ) : (
    ""
  );
};
export default GuardedRoute;

并在app.js中用途:

import RouterPage from "./pages/RouterPage";
<GuardedRoute path="/router-page" component={RouterPage} />

在Vue中:在路由器文件中用途:

const guardSuccess = (to, from, next) => {
  let gUser = auth.currentUser
  if (gUser) {
    next()
  } else {
    next({ name: "Home" })
  }
}

并在要限制访问的页面的路由中添加:

{
    path: "/router-page",
    name: "routerPage",
    component: () => import("../views/routerPage.vue"),
    beforeEnter: guardSuccess
  }
ve7v8dk2

ve7v8dk29#

firebase.auth().onAuthStateChanged(function(user) {
    if (user) {

      var user = firebase.auth().currentUser;

      if(user != null){ 
        var io=user.uid;
        window.alert("success "+io);



      }

    } else {
      // No user is signed in.
      Window.reload();

    }
  });

首先检查用户是否存在,然后通过以下方式获取其ID
当前用户.uid

相关问题