How to avoid inject warning in beforeEach? - vue.js

I use Pinia in a Quasar project.
When the code is according the doc from pinia, it creates a warning:
import {useAuthStore} from "stores/auth-store";
import { useRouter } from 'vue-router'
const router = useRouter()
const beforeEach = ((to, from, next) => {
const store = useAuthStore()
if (to.meta.needsAuth) {
if (store.authenticated) {
next()
}
else {
router.push('/')
}
} else {
next()
}
})
export default beforeEach
Warning:
[Vue warn]: inject() can only be used inside setup() or functional components.
I followed the doc from Pinia:
https://pinia.vuejs.org/core-concepts/outside-component-usage.html#single-page-applications
If I set const store = useAuthStore() before the const store = useAuthStore() there is an error.
How do I have to modify the code to avoid the warning?

Related

[Vue warn]: inject() can only be used inside se.... I read post related to this error and understood the cause of error, but I'm not sure what to do

I have encounted the below error.
[Vue warn]: inject() can only be used inside setup() or functional components.
This error occurs when await keyword is behind inject().
useRoute() and useRouter() use inject() internally.
I knew the meaning of error and I assume that the await keyword is the cause of the error.
But I'm not sure what to do.
Could you tell me what code I should modify?
Here is my code.
// router.js
import * as VueRouter from 'vue-router'
import CategoryHome from './components/CategoryHome.vue'
import CategoryShow from './components/CategoryShow.vue'
const routes = [
(abbreviation)
]
const router = VueRouter.createRouter({
(abbreviation)
})
export default router
// function.js
import { ref } from "vue"
import router from './router.js'
let categoryId = ''
export async function initial() {
try {
const res = await axios.get('/api/max')
categoryId = res.data.id
router.push({name: 'category.show', params: { categoryId: categoryId }})
} catch(err) {
console.log('error handling')
}
}
// CategoryHome.vue
<script setup>
import { onMounted, ref } from "vue"
import * as func from '../functions.js'
import router from '../router.js'
const newCategory = ref('')
onMounted(() => {
func.initial()
})
Thank you for your help.

how to use pinia store in a vue router navigation guard?

I'm using Vuejs 3, vuerouter 4 and pinia and trying to put a navigation guard in some routes, as per the example in the documentation (if a user is not authenticated and is not on the login page, send the user to login page to get authenticated). This is explained also in pinia documentation on use of pinia outside of components. But I can't get my head around it.
The store I use is currently simple (return false or true on isAuthenticated):
//authStore.js
import { defineStore } from "pinia";
export const useAuthStore = defineStore( 'AuthStore', {
state: () => {
return {
isAuthenticated: false
}
}
})
I want to use this isAuthenticated in a beforeEnter in routes/index.js
In main.js:
import { useAuthStore } from '#/stores/authStore'
import { createApp } from 'vue'
import App from './App.vue'
import router from '#/router'
import { createPinia } from 'pinia'
const app = createApp(App)
app.use(createPinia()).use(router)
app.mount('#app')
// I'm not using authStore in this file, so this raises an error:
const authStore = useAuthStore()
And in router/index.js:
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
// path for login page,
{
path: '/adm/home',
name: 'AdmView',
component: () => import('#/views/adm/AdmView.vue'),
beforeEnter: (to) => {
// error: authStore is not defined
const isAuthenticated = authStore
if ( !isAuthenticated && to.name !== 'login-adm' ) {
return { name: 'login-adm' }
}
}
},
// other paths
]
Your authStore.js exports useAuthStore as expected, but you do not call it as required.
authStore is not defined because authStore is the filename of your auth store -- instead you should be executing the function useAuthStore exported from that file:
const authStore = useAuthStore();
console.log('Is authenticated?', authStore.isAuthenticated);
I don't know if it is the main issue but u forgot to use a destructor on userStore doing
const isAuthenticated = authStore
It supposed to be
const { isAuthenticated } = toRefs(authStore);
toRefs to preserve reactivity after passing. It can be imported as
import { toRefs } from 'vue';

Vue3 route.query empty

Trying to pass route query to axios request, but it is empty..
route.query returns empty in mounted. route.queryreturns {"filter[city]": "Vilnius" } in axios then
nextTick doesn't solve issue. Any tips?
import { ref, onMounted, nextTick } from 'vue';
import axios from 'axios';
import { useRouter, useRoute } from 'vue-router';
export default {
setup() {
const router = useRouter();
const route = useRoute();
onMounted(() => {
console.log(route.query); // log is {}
fetchApartments();
});
function fetchApartments() {
console.log(route.query); // log is {}
axios.get('/api/apartments').then(response => {
console.log(route.query); // log is { "filter[city]": "Vilnius" }
});
}
}
}
Route navigation is asynchronous. You need to wait for router.isReady for queries to be available
import {useRouter, useRoute} from 'vue-router';
export default {
setup() {
const router = useRouter();
const route = useRoute();
onMounted(async () => {
await router.isReady();
console.log(route.query);
});
}
}
Update your code like this:
...
import { computed } from 'vue'
...
and inside setup()
const route = useRoute();
const query = computed(() => route.query)
The missing part here is computed property.

How to access router from nuxtjs store?

I tried this but only got an error message
This relative module was not found:
* ./router in ./store/index.js
// Ran with yarn dev
import router from './router'
export const state = () => ({
authenticated: false,
})
export const mutations = {
toggleLogin(state, loginStatus, path) {
state.authenticated = loginStatus
if (loginStatus) {
router.push(path)
} else {
router.push('login')
}
},
}
My store path is store/index.js
Vuex mutations and getters doesn't have access to the Vue context. Only actions does.
Also, you can't import the Nuxt router like that. What's that file you're trying to import?
I'd suggest to make an action instead:
export const actions: {
toggleLogin({ commit }, payload) {
this.app.router.push('') //exists
}
}

Problem importing getters into Router - Vuex

Problem importing getters into Rotate - Vuex.
I am trying to import a value that is within the vuex state.
An error is reported, stating that it is undefined.
I have no idea what I might have done wrong. Please, if anyone can help, I will be very grateful.
Thanks for listening
Error
TypeError: "_store__WEBPACK_IMPORTED_MODULE_4__.default.getters is undefined"
Store
import Vue from 'vue'
import Vuex from 'vuex'
import auth from './module-auth'
Vue.use(Vuex)
export default function () {
const Store = new Vuex.Store({
modules: {
auth
},
strict: process.env.DEV
})
return Store
}
module-auth
Getters
import decode from 'jwt-decode'
function isTokenExpired (state) {
try {
const decoded = decode(state.token)
if (decoded.exp < Date.now() / 1000) {
return true
} else return false
} catch (err) {
return false
}
}
export {
isTokenExpired,
}
Router
import Vue from 'vue'
import VueRouter from 'vue-router'
import routes from './routes'
import store from '../store'
Vue.use(VueRouter)
export default function () {
const Router = new VueRouter({
scrollBehavior: () => ({ x: 0, y: 0 }),
routes,
mode: process.env.VUE_ROUTER_MODE,
base: process.env.VUE_ROUTER_BASE
})
Router.beforeEach((to, from, next) => {
const publicPages = ['/']
const authRequired = !publicPages.includes(to.path)
const loggedIn = store.getters['auth/isTokenExpired']
console.log(loggedIn)
if (authRequired && !loggedIn) {
return next('/')
}
next()
})
return Router
}
Your mistake is that you try to use a function as Vuex module.
Module should be an object.
Docs say:
export const moduleA = {
state: { count: 0 },
mutations: {
increment(state) {
state.count++;
}
},
getters: {
doubleCount(state) {
return state.count * 2;
}
}
};
And your function isTokenExpired looks like it should be placed in "getters" section.
Exporting a function that create a store and use it as a function will create many stores and is not desired.
Since you need to use one instance of store anywhere, you need to export the store instance, not a function that create a store.