I'm currently working on my first vue application, currently building the login logics. For State management, pinia is being used. I created a Pinia Store to manage the "isLoggedIn" state globally.
import { defineStore } from "pinia";
export const useLoginStatusStore = defineStore('loginStatus', {
id: 'loginStatus',
state: () => ({
isLoggedIn: false
}),
actions: {
logIn() {
this.isLoggedIn = true
console.log("Login", this.isLoggedIn)
},
logOut() {
this.isLoggedIn = false
console.log("Logout", this.isLoggedIn)
}
}
})
So far so good, its working, i can access the state and actions in the components and router file.
**<roouter.js>**
import { createRouter, createWebHistory } from 'vue-router'
import { createPinia } from 'pinia'
import { createApp, ref } from 'vue'
import { useLoginStatusStore } from '../stores/loginStatus.js'
import App from '../App.vue'
import WelcomeView from '../views/public/WelcomeView.vue'
import SplashView from '../views/public/SplashView.vue'
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
const loginStatusStore = useLoginStatusStore()
let isLoggedIn = ref(loginStatusStore.isLoggedIn)
console.log("isLoggedIn", loginStatusStore.isLoggedIn)
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'splash',
component: SplashView
},
{
path: '/welcome',
name: 'welcome',
component: WelcomeView
},
{
path: '/login',
name: 'login',
component: () => import('../views/public/LoginView.vue')
},
{
path: '/signup',
name: 'signup',
component: () => import('../views/public/SignUpView.vue')
},
{
path: '/resetpassword',
name: 'resetpassword',
component: () => import('../views/public/ForgotPasswordView.vue')
},
{
path: '/home',
name: 'home',
component: () => import('../views/protected/HomeView.vue'),
meta: { requiresAuth: true }
},
{
path: '/sounds',
name: 'sounds',
component: () => import('../views/protected/SoundsView.vue'),
meta: { requiresAuth: true }
},
{
path: '/player',
name: 'soundPlayer',
component: () => import('../views/protected/SoundPlayerView.vue'),
meta: { requiresAuth: true }
},
{
path: '/profile',
name: 'profile',
component: () => import('../views/protected/ProfileView.vue'),
meta: { requiresAuth: true }
},
{
path: '/meditation',
name: 'meditation',
component: () => import('../views/protected/MeditationView.vue'),
meta: { requiresAuth: true }
},
{
path: '/tools',
name: 'tools',
component: () => import('../views/protected/ToolsView.vue'),
meta: { requiresAuth: true }
}
]
})
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth) {
console.log("Router", isLoggedIn.value)
if (!isLoggedIn.value) {
next({
name: 'welcome'
})
} else {
next()
}
} else {
next()
}
})
export default router
In the router it's being used for protected routes and in App.vue for conditional class rendering.
The Problem is, that when the state gets updated, it doesn't get updated in the components and the components themselves don't update either. I tried with the $subscribe method in pinia, but didnt manage to get it working. I know, whats needed is something that creates reactivity here. But no clue how to do that. I'm grateful for any help with this :)
thanks for reading
**App.vue**
<script setup>
import { RouterView } from 'vue-router';
import DevNavItem from '@/components/header/DevNavItem.vue'
import HeaderItem from '@/components/header/HeaderItem.vue'
import FooterItem from '@/components/footer/FooterItem.vue'
import { useLoginStatusStore } from './stores/loginStatus.js';
const loginStatusStore = useLoginStatusStore()
const isLoggedIn = loginStatusStore.isLoggedIn
console.log("App.vue", loginStatusStore.isLoggedIn)
</script>
<template>
<DevNavItem />
<HeaderItem v-if="isLoggedIn" />
<RouterView :class="isLoggedIn ? 'mainProtected' : 'mainPublic'" />
<FooterItem v-if="isLoggedIn" />
</template>
<style>
/*FONT-IMPORT*/
@import url("@/assets/font/alegreya_font.scss");
/* GENERAL STYLES */
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
header {
position: top;
}
.mainProtected {
width: 100vw;
height: 83vh;
overflow: hidden;
}
.mainPublic {
width: 100vw;
height: 100vh;
overflow: hidden;
}
/* GLOBAL CLASSES */
.mainLogo {
height: 350px;
width: 350px;
background: url("./img/icons/main.png") center/cover no-repeat;
}
.leavesBackground {
background-color: #253334;
background-image: url("./src/img/images/background_partial.png");
background-repeat: no-repeat;
background-position: bottom;
background-size: contain;
}
.logoSmall {
background: url("./img/icons/main.png") center/contain no-repeat;
height: 100px;
width: 100px;
}
.buttonPublic {
padding: 20px 0;
text-align: center;
background-color: #7c9a92;
color: #fff;
border-radius: 15px;
width: 90%;
text-decoration: none;
font-size: 24px;
border: none;
}
</style>
I tried subscribing to the state with $subscribe, but it didn't work.