How to access store values to components in vue js - vue.js

This is my store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
isLoggedIn: !!localStorage.getItem('token'),
isLog : !!localStorage.getItem('situation')
},
mutations: {
loginUser (state) {
state.isLoggedIn = true
state.isLog = true
},
logoutUser (state) {
state.isLoggedIn = false
state.isLog = false
},
}
})
but when I call {{state.isLoggedIn}} in the display.vue, I am not getting the values.
In display.vue, I use
<script>
import axios from "axios";
import store from '../store';
export default {
name: "BookList",
data() {
return {
students: [],
errors: [],
state: this.state.isLoggedIn,
};
},
})
</script>
<template>
{{this.state}}
</template>
But I am getting errors when i done this way. Please can anyone please help what is the problem.

You don't need to import your store into your component. Instead, you should access it using this.$store.
For accessing the store state, the better (and recommended) way is to map the state within your component.
In your example it should be something like:
import { mapState } from 'vuex'
export default {
...
computed: {
...mapState({
isLoggedIn: 'isLoggedIn'
})
}
}
In your template, this is not needed. Just call the property by its name:
{{ isLoggedIn }}

Related

Vue3 Pinia Store cannot access 'store" before initializsation

I have a UserStore which contains some information about the current user. This store also is responsible for loggin in and out.
In order to make the getters available I map the getters to my computed attribute within my Vue component.
Unfortunately I get an error saying that it cannot access useUserStore before initilization.
This is my component:
<template>
//...
</template>
<script>
import {mapState} from "pinia"
import {useUserStore} from "../../stores/UserStore.js";
import LoginForm from "../../components/forms/LoginForm.vue";
export default {
name: "Login",
components: {LoginForm},
computed: {
...mapState(useUserStore, ["user", "isAuthenticated"]) //commenting this out makes it work
}
}
</script>
This is my store:
import { defineStore } from 'pinia'
import {gameApi} from "../plugins/gameApi.js"
import {router} from "../router.js";
export const useUserStore = defineStore("UserStore", {
persist: true,
state: () => ({
authenticated: false,
_user: null
}),
getters: {
user: (state) => state._user,
isAuthenticated: (state) => state.authenticated
},
actions: {
async checkLoginState() {
// ...
},
async loginUser(fields) {
// ...
},
async logutUser() {
// ...
}
}
})
And my main.js
import {createApp} from 'vue'
import App from './App.vue'
import gameApi from './plugins/gameApi'
import {router} from './router.js'
import store from "./stores/index.js";
createApp(App)
.use(store)
.use(router)
.use(gameApi)
.mount('#app')
And finally my store configuration:
import {createPinia} from "pinia"
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import {useUserStore} from "./UserStore.js";
const piniaStore = createPinia()
piniaStore.use(piniaPluginPersistedstate)
export default {
install: (app, options) => {
app.use(piniaStore)
const userStore = useUserStore()
const gameStore = useGameStore()
}
}
I wasn't able to initialize the store using the "old" way comparable with Vuex. Instead I had to make use of the setup() function Pinia Docu:
<script>
import {useUserStore} from "../../stores/UserStore.js";
export default {
name: "RegisterForm",
setup() {
// initialize the store
const userStore = useUserStore()
return {userStore}
},
data() {
return {
// ...
}
},
methods: {
checkLoginState() {
this.userStore.checkLoginState()
}
}
}
</script>

Pinia getter does not filter state (options API)

I have a pinia store I am using with a vue component, with the options API. I have a getter in my pinia store that is supposed doing some basic filtering of items. However, the getter just returns what is in state without any of the filtering applied.
My component:
<template>
<DetailsWrapper :filteredDetails="filteredDetails"
</template>
<script>
import {mapState, } from 'pinia';
export default {
components: DetailsWrapper,
computed: {
...mapState(useDetailsStore, {
filteredDetails: store => store.filteredDetails,
},
};
</script>
In my pinia store I have:
import axios from 'axios';
import { defineStore } from 'pinia';
const useDetailsStore = defineStore('details', {
getters: {
filteredDetails: state => {
const productDetails = state.product && state.product.details;
productDetails.forEach(detail => {
detail.values.filter(detail => detail.isOnline && detail.isDisplayable
});
return productDetails
},
});
export default useDetailsStore
The end result is just that everything in productDetails is returned -- nothing is filtered out, even though there are definitely values to be filtered.
If anyone could provide any guidance it would be much appreciated!
You can try like this:
import axios from 'axios';
import { defineStore } from 'pinia';
const useDetailsStore = defineStore('details', {
getters:
{
filteredDetails(state)
{
return (state.product?.details || []).map(product => ({
...product,
values: product.values.filter(val => val.isOnline && val.isDisplayable),
});
},
});
export default useDetailsStore;

Can't access store from Vuex [Quasar]

I'm trying Quasar for the first time and trying to use the Vuex with modules but I can't access the $store property nor with ...mapState. I get the following error 'Cannot read property 'logbook' of undefined' even though I can see that the promise logbook exists on Vue Devtools. Print from Devtools
Here is my store\index.js
import Vue from 'vue';
import Vuex from 'vuex';
import logbook from './logbook';
Vue.use(Vuex);
export default function (/* { ssrContext } */) {
const Store = new Vuex.Store({
modules: {
logbook,
},
strict: process.env.DEV,
});
return Store;
}
Here is the component
<template>
<div>
<div>
<h3>RFID</h3>
<q-btn #click="logData"
label="Save"
class="q-mt-md"
color="teal"
></q-btn>
<q-table
title="Logbook"
:data="data"
:columns="columns"
row-key="uid"
/>
</div>
</div>
</template>
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
export default {
name: 'RFID',
mounted() {
this.getLogbookData();
},
methods: {
...mapActions('logbook', ['getLogbookData']),
...mapGetters('logbook', ['loadedLogbook']),
...mapState('logbook', ['logbookData']),
logData: () => {
console.log(this.loadedLogbook);
},
},
data() {
return {
};
},
};
</script>
<style scoped>
</style>
Here is the state.js
export default {
logbookData: [],
};
Error that I get on the console
Update: Solved the problem by refactoring the way I declared the function. I changed from:
logData: () => { console.log(this.loadedLogbook); }
to
logData () { console.log(this.loadedLogbook); }
Check the .quasar/app.js file. Is there a line similar to import createStore from 'app/src/store/index', and the store is later exported with the app in that same file?
I think you confused all the mapx functions.
...mapState and ...mapGetters provide computed properties and should be handled like this
export default {
name: 'RFID',
data() {
return {
};
},
mounted() {
this.getLogbookData();
},
computed: {
...mapGetters('logbook', ['loadedLogbook']),
...mapState('logbook', ['logbookData']),
}
methods: {
...mapActions('logbook', ['getLogbookData']),
logData: () => {
console.log(this.loadedLogbook);
},
}
};

Vuex. Again: Computed properties are not updated after Store changes. The simplest example

I did really read all Google!
Store property "sProp" HAS initial value (=10);
I use Action from component to modify property;
Action COMMITS mutation inside the Store Module;
Mutation uses "Vue.set(..." as advised in many tickets
Component uses mapState, mapGetters, mapActions (!!!)
I also involve Vuex as advised.
I see initial state is 10. But it is not changed after I press button.
However if I console.log Store, I see it is changed. It also is changed in memory only once after the 1st press, but template always shows 10 for both variants. All the other presses do not change value.
Issue: my Computed Property IS NOT REACTIVE!
Consider the simplest example.File names are in comments.
// File: egStoreModule.js
import * as Vue from "vue/dist/vue.js";
const state = {
sProp: 10,
};
const getters = {
gProp: (state) => {
return state.sProp;
}
};
const mutations = {
//generic(state, payload) {},
mProp(state, v) {
Vue.set(state, "sProp", v);
},
};
const actions = {
aProp({commit}, v) {
commit('mProp', v);
return v;
},
};
export default {
namespaced: true
, state
, getters
, mutations
, actions
}
And it's comsumer:
// File: EgStoreModuleComponent.vue
<template>
<!--<div :flag="flag">-->
<div>
<div><h1>{{sProp}} : mapped from Store</h1></div>
<div><h1>{{$store.state.egStoreModule.sProp}} : direct from Store</h1></div>
<button #click="methChangeProp">Change Prop</button>
<button #click="log">log</button>
</div>
</template>
<script>
import {mapActions, mapGetters, mapState} from "vuex";
export default {
name: 'EgStoreModuleComponent',
data() {
return {
flag: true,
};
},
computed: {
...mapState('egStoreModule', ['sProp']),
...mapGetters('egStoreModule', ['gProp'])
},
methods: {
...mapActions('egStoreModule', ['aProp']),
methChangeProp() {
const value = this.sProp + 3;
this.aProp(value);
//this.flag = !this.flag;
},
log() {
console.log("log ++++++++++");
console.log(this.sProp);
},
}
}
</script>
<style scoped>
</style>
Here is how I join the Store Module to Application:
// File: /src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import collection from "./modules/collection";
import egStoreModule from "./modules/egStoreModule";
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {},
getters : {},
mutations: {},
actions : {},
modules : {
collection,
egStoreModule
}
});
Finally: main.js
import Vuex from 'vuex'
import {store} from './store'
//...
new Vue({
el: '#app',
router: router,
store,
render: h => h(App),
})
It all works if only I use "flag" field as shown in comments.
It also works if I jump from page and back with Vue-router.
async/await does not help.
I deleted all under node_modules and run npm install.
All Vue/Vuex versions are the latest.

Vuex $state issue

I have error like this:
I previously thought that this is problem with router, but after creating new project with only vuex problem is still there
enter image description here
This is my main.js
import Vue from 'vue'
import App from './App'
import store from './store'
new Vue({
el: "#app",
store,
render: h => h(App)
})
store.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const store = new Vuex.Store({
state: {
users: [
{id: 1, name: 'Adrian', email: 'adrian#email.pl'},
{id: 2, name: 'Magda', email: 'magda#email.pl'}
]
}
})
and my component using $store:
<template>
<div class="usersNames">
<ul>
<li v-for="user in usersNames">{{user.name}}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'usersNames',
computed: {
usersNames() {
return this.$store.state.users;
}
}
}
</script>
Your examples look like it should work, but I would like to offer a different strategy that I think would be an improvement and should also solve your problem.
Create a getter in your store for the data you're trying to access in your component.
So change your store to this:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const store = new Vuex.Store({
state: {
users: [
{id: 1, name: 'Adrian', email: 'adrian#email.pl'},
{id: 2, name: 'Magda', email: 'magda#email.pl'}
]
},
getters:{
users: state => return state.users
}
});
Then, in your component, use that getter to get your users.
<script>
export default {
name: 'usersNames',
computed: {
usersNames() {
return this.$store.getters.users
}
}
}
</script>
you could change main.js:import {store} from './store';
Seems your vuex not inject into vue properly.
Maybe not related to your question, but just for best practice, better use mapState helper;
In your component:
import { mapState } from 'vuex'
export default {
name: 'usersNames',
computed: {
...mapState({
usersNames: 'users'
}),
yourLocalComputed () {}
}
}