로드에서 현재 사용자를 가져올 수 없습니다.
사용자가 로그인되었는지 확인하려고 할 때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...!
여기서 무슨 일이 일어나고 있는지 잘 모르겠어요.저는 리액트와 리덕스를 사용하고 있지만, 제가 말하는 것은 별로 중요하지 않습니다.
파이어베이스가 초기화되고 현재 사용자에 액세스할 수 없는 약간의 지연이 있습니까?그렇다면 의 로그 출력에서 어떻게 확인할 수 있습니까?firebase.auth()
?
이것은 일반적으로 묻는 질문입니다.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.
}
});
간단한 방법은 보류 중인 상태를 추가하는 것입니다.
다음은 후크를 사용한 반응 예제입니다.
Auth.
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>
)
}
currentUser에 항상 액세스할 수 있는 가장 좋은 방법은 vuex 및 vuex 지속 상태를 사용하는 것입니다.
//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 상태가 사라지고 AuthStateChange에서 다시 시작될 때까지 기다려야 하므로 현재 사용자에 액세스하려고 하면 null이 발생하는 이유입니다.
위 코드가 항상 작동하는 비결은 vuex-persisted 상태를 사용하는 것입니다.
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()
}
})
Firebase와의 대응을 위해 Auth 경로를 복사하여 붙여넣으려는 경우:
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' }} />
)}
/>
)
}
다음과 같은 세 가지 옵션이 있습니다.
업데이트: 11/26/22
Firebase 9+의 경우 다음을 수행할 수 있습니다.
참고: (이 .auth)는 Auth 개체이며 프레임워크에 따라 다릅니다.
const user1 = await firstValueFrom(authState(this.afa));
const user2 = await firstValueFrom(
new Observable(observer => onAuthStateChanged(this.afa, observer))
);
const user3 = this.afa.currentUser;
// 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);
TL;DR:
expo sdk를 사용하여 여기에 오는 사람들을 위해.>=48
또는 React Native를 업데이트한 후>=0.71
화재 기지를 초기화해야 합니다.다음과 같은 사용자 지정 스토리지로 인증:
import { initializeAuth } from 'firebase/auth';
import { getApp } from 'firebase/app';
import { getReactNativePersistence } from 'firebase/auth/react-native';
import ReactNativeAsyncStorage from '@react-native-async-storage/async-storage';
const storage = getReactNativePersistence(ReactNativeAsyncStorage)
const app = getApp();
initializeAuth(app, {
persistence: storage,
});
설명:
AsyncStorage
오래 전부터 사용되지 않아 V 0.71의 React Native에서 제거되었습니다.안타깝게도 Firebase 인증은 여전히 후드 아래 통합된 AsyncStorage에 의존하고 있습니다.
그 결과, 즉, (사용할 때에도)onAuthStateChanged
위의 답변에서 설명한 바와 같이)getAuth().currentUser
항상 그럴 것입니다.null
앱을 닫았다가 다시 연 후.
이 문제는 https://github.com/firebase/firebase-js-sdk/pull/7128 에서 자세히 설명합니다.
// 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*/}
이를 위한 최선의 방법은 약속을 사용하고 응답 후에만 라우터를 인스턴스화하는 것입니다. 이는 다음과 같습니다.
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')
})
내부의다음과 같이 약속을 지킬 수 있는 곳이 바로 Auth Action입니다.
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 - 저에게 이 해결책의 원천입니다.
사용자가 인증된 경우에만 특정 페이지에 액세스하고 인증되지 않은 경우 홈 페이지로 리디렉션하려면 다음 코드가 도움이 될 수 있습니다.
반응: 다음 코드로 구성 요소를 만듭니다.
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} />
in 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
}
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를 가져옵니다.
화력 기지auth().currentUser.uid
언급URL : https://stackoverflow.com/questions/37883981/cant-get-currentuser-on-load
'sourcecode' 카테고리의 다른 글
스레드화에서 join()의 용도는 무엇입니까? (0) | 2023.06.27 |
---|---|
열의 값이 고유한지 확인하기 위한 SQL 쿼리 (0) | 2023.06.27 |
OS X "El Capitan"에 보석을 설치할 수 없습니다. (0) | 2023.06.27 |
PL/SQL에서 출력을 새 줄로 인쇄하려면 어떻게 해야 합니까? (0) | 2023.06.27 |
Vuex getter 및 돌연변이 이해 (0) | 2023.06.27 |