dicem
@dicem

Как заставить beforeRouter дождаться пока в firebase подтвердит авторизацию?

Делаю простое приложение по серии уроков из https://youtu.be/DlXSA3_lSX4.
Дошел до момента, когда в роутинге проверяем залогинен ли пользователь и отправляем в соответствующие страницы:
router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'

// Routes
import Home from '@/views/Home'
import TasksPage from '@/views/TasksPage'
import Login from '@/views/Auth/Login'
import Registration from '@/views/Auth/Registration'

import store from '../store'

Vue.use(VueRouter)

const routes = [
	{
		path: '/',
		name: 'home',
		component: Home,
		beforeEnter(to, from, next) {
			store.getters.checkUser ? next() : next('/login')
		}
	},
	{
		path: '/tasks',
		name: 'tasks',
		component: TasksPage,
		beforeEnter(to, from, next) {
			store.getters.checkUser ? next() : next('/login')
		}
	},
	{
		path: '/login',
		name: 'login',
		component: Login,
		beforeEnter(to, from, next) {
			!store.getters.checkUser ? next() : next('/')
		}
	},
	{
		path: '/registration',
		name: 'registration',
		component: Registration,
		beforeEnter(to, from, next) {
			!store.getters.checkUser ? next() : next('/')
		}
	}
]

const router = new VueRouter({
	mode: 'history',
	base: process.env.BASE_URL,
	routes
})

export default router



beforeEnter проверяет checkUser, который в свое время в модуле стора выглядит по дефолту так:
store/user.js

import firebase from 'firebase/app'

import User from './user_help'

export default {
	state: {
		user: null
	},
	mutations: {
		setUser(state, payload) {
			state.user = payload
		}
	},
	actions: {
		async registerUser({commit}, {email, password}) {
			commit('clearError')
			commit('setLoading', true)
			try {
				const user = await firebase.auth().createUserWithEmailAndPassword(email, password)
				commit('setUser', new User(user.user.uid))

				commit('setLoading', false)
			} catch (err) {
				commit('setLoading', false)
				commit('setError', err.message)
				throw err
			}
		},
		async loginUser({commit}, {email, password}) {
			commit('clearError')
			commit('setLoading', true)
			try {
				const user = await firebase.auth().signInWithEmailAndPassword(email, password)
				commit('setUser', new User(user.user.uid))

				commit('setLoading', false)
			} catch (err) {
				commit('setLoading', false)
				commit('setError', err.message)
				throw err
			}
		},
		loggedUser({commit}, payload) {
			commit('setUser', new User(payload.uid))
		},
		logoutUser({commit}) {
			firebase.auth().signOut()
			commit('setUser', null)
		}
	},
	getters: {
		user(state) {
			return state.user
		},
		checkUser(state) {
			return state.user !== null
		}
	}
}


Для изменения user в стейте есть мутация setUser и тот класс User, что она использует так же импортирован:
export default class User {
	constructor(id) {
		this.id = id
	}
}

В main.js перед всем этим делом по сути должен отрабатывать метод created():
main.js

new Vue({
	router,
	store,
	render: h => h(App),
	created() {
		const firebaseConfig = {
			apiKey: "...",
			authDomain: "...",
			databaseURL: "...",
			projectId: "...",
			storageBucket: "...",
			messagingSenderId: "...",
			appId: "..."
		}
		firebase.initializeApp(firebaseConfig)

		firebase.auth().onAuthStateChanged( user => {
			if (user) {
				this.$store.dispatch('loggedUser', user)
			}
		})
	}
}).$mount('#app')



Суть ошибки заключается в том, что теперь когда я обновляю страницу с веб приложением будучи авторизованым пользователем, beforeEnter не дожидаясь пока firebase проверит меня на авторизацию использует дефолтное значение null и перекидывает меня на страницу логина. та же самая история происходит с навигацией которую я реализовал следующим образом:
Navbar.vue

...
		computed: {
			checkUser() {
				return this.$store.getters.checkUser
			},
			linkMenu() {
				if (this.checkUser) {
					return [
						{ name: 'Home', url: '/' },
						{ name: 'Tasks', url: '/tasks' }
					]
				}
				return [
					{ name: 'Login', url: '/login' },
					{ name: 'Registration', url: '/registration' }
				]
			}
		}
...


То есть сначала checkUser получает дефолтное false, отрабатывает его по текущему значению и потом исправляется реактивно, после того как firebase подтвердил авторизацию.
  • Вопрос задан
  • 99 просмотров
Решения вопроса 1
0xD34F
@0xD34F Куратор тега Vue.js
Поменяйте порядок действий - сначала авторизация, потом создание экземпляра vue:

firebase.auth().onAuthStateChanged(user => {
  if (user) {
    store.dispatch('loggedUser', user);
  }

  new Vue(...);
});
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы