Vue, flow between Vuex and Vue component - vue.js

Im devoloping a Vue Frontend and my problem is the flow between Vuex and vue component.
Vuex component
const state = () => ({
User: {
Firstname: '',
Lastname: '',
MainAccountBalance: '',
SubAccount: []
}
})
const getters = {
getUserData(state) {
console.log("3 Dashboard: getter")
return state.User;
}
};
const actions = {
async fetchUserProfile({commit}, payload) {
await instance.post(UserAccounts, {
token: payload.token
})
.then(response => {
console.log("1 Dashboard: fetchUserProfile");
commit('saveAccounts', response.data);
return JSON.stringify(response.data);
})
}
};
const mutations = {
saveAccounts(state, data) {
const newModel = {
Firstname: data.Firstname,
Lastname: data.Fastname,
MainAccountBalance: data.MainAccountBalance,
SubAccount: data.SubBankAccounts
}
console.log("2 Dashboard: Mutations")
state.User = newModel;
}
};
fetchUserProfile is getting called from Vue component and gets commited to saveAccounts where it will set data for state variables. All of this works fine, and in correct order. The problem starts with when i want to get the data from the State using getters.
Vue component
computed: {
...mapGetters("auth", {
getUserData: 'getAuthData'
}),
},
methods: {
...mapActions("dashboard", {
userProfileaction: "fetchUserProfile"
}),
getUserToken() {
this.access_token = localStorage.getItem("access_token")
return this.access_token;
},
async saveUserData() {
var userToken = this.getUserToken();
await this.fetchUserProfile({token: userToken})
this.Firstname = this.getUserData.Firstname;
this.Lastname = this.getUserData.Lastname;
console.log("Last Show accounts: "+ this.getUserData.User.Firstname)
}
},
mounted() {
this.saveUserData()
console.log("test")
}
How would i use getters correct so it doesent execute before the variables are set on Vuex? Is there an better alternative way?

Related

Unable to store data in vuex "State"

I am unable to store the data from the API in the state, is there any issue in my code?
I am not able to console.log(state.token) or state.token from the mutations.
My Store
export const AUTH_MUTATIONS = {
SET_USER: 'SET_USER',
SET_PAYLOAD: 'SET_PAYLOAD',
LOGOUT: 'LOGOUT',
}
export const state = () => ({
token: null,
userdata: [],
data: [],
})
export const mutations = {
[AUTH_MUTATIONS.SET_USER] (state, { userdata }) {
state.userdata = userdata
},
[AUTH_MUTATIONS.SET_PAYLOAD] (state, { token }) {
state.token = token
},
}
export const actions = {
async login ({ commit, dispatch }, { email_id, password }) {
const { data: {data: { user, token } } } = await this.$axios.post('http://18.xxx.246.xxx:5000/api/v1/users/login',
{
email_id,
password
})
// console.log(user)
// console.log(token)
commit(AUTH_MUTATIONS.SET_USER, user)
commit(AUTH_MUTATIONS.SET_PAYLOAD, token)
// console.log(AUTH_MUTATIONS.SET_USER, user)
},
}
export const getters = {
isAuthenticated: (state) => {
return state.token && state.token !== ''
},
}
In your action you need to take in state in the destructured parameters like this: { commit, dispatch, state } then you will be able to access your state and log state.token.
If it's still null after that point then you should debug it to ensure that you're setting it correctly in the mutation itself.

Vuex is not mutating the state

I am trying to switch authenticated from false to true, a property in the state, It's not working.
My codes from store.js
state() {
return{
authenticated : false,
user : {}
}
},
getters : {
authenticated(state){
return state.authenticated
}
},
mutations : {
set_authenticated(state, value){
return state.authenticated = value
}
},
My updated code from login.vue (script)
data() {
return {
allerrors : [],
success : false,
data: {
email : "",
password : ""
}
}
},
methods : {
login: function() {
this.$store
.dispatch("login", this.data)
.then(response => {
this.allerrors = [],
this.success = true,
this.data = {}
alert(response.data)
})
.catch((error) => {
this.allerrors = error.response.data.error
this.success = false
alert(allerrors)
})
},
My updated action is :
async login({ commit }, data) {
await axios.post('login', data)
.then(response => {
commit('set_authenticated',true);
})
.catch((error) => {
this.allerrors = error.response.data.error
this.success = false
})
}
There are a few problems here:
First, if that is the full code for your store.js file, then you are missing the call to createStore() (for Vue 3) or new Vuex.Store() (for Vue 2)
import { createStore } from 'vuex'
// Create a new store instance.
const store = createStore({
state () {
return {
count: 0
}
},
mutations: {
increment (state) {
state.count++
}
}
})
Source
The second problem is that you shouldn't be committing mutations from your Single File Components. The typical flow is:
Components dispatch actions
Actions commit mutations
Mutations update state
You're trying to commit a mutation directly from the component.
You need to add an action to your store.js
async login({ commit }, userData) {
await axios.post('login', userData)
.then(response => {
commit('set_authenticated',true);
})
.catch((error) => {
this.allerrors = error.response.data.error
this.success = false
})
}
Mutation:
mutations : {
set_authenticated(state, value){
state.authenticated = value
}
},
Then your Login.vue would change to something like:
methods: {
login: function() {
this.$store
.dispatch("login", { userData })
.then(() => )) // whatever you want to do here.
.catch(err => console.error(err));
}
}
mutations shouldn't have a return statement. it should be like this
mutations : {
set_authenticated(state, value){
state.authenticated = value
}
},

How to dispatch store actions in namespaced modules ( NuxtJS)?

I have made lots of research and since keywords are always similar I cannot find a correct way of usage store modules in nuxtjs. I will shorten the codes to make it readable. In my nuxtjs application, I am trying to reach my vuex modules in my home.page but instead I get
pages/index.vue
TypeError
Cannot read property 'then' of undefined
created() {
this.$store.dispatch('articles/fetchIndexArticles')
.then(() => this.$store.dispatch('videolessons/fetchIndexVideolessons'))
.then(() => {
While creating modules first in the store folder i have created an index.js file:
import Vuex from "vuex";
import articles from "./modules/articles";
// ...
import videolessons from "./modules/videolessons";
const debug = process.env_NODE_ENV !== 'production';
export const store = new Vuex.Store({
modules: {
articles,
books,
members,
pages,
status,
user,
videolessons,
},
strict: debug,
plugins: [],
})
and basically my modules are similar to my articles module:
const getDefaultState = () => {
return {
indexArticles: [],
}
}
const state = getDefaultState()
const getters = {
indexArticles (state) {
return state.indexArticles
},
}
const mutations = {
fetchStart (state) {
state.loading = true
},
fetchEnd (state) {
state.loading = false
},
setIndexArticles (state, pArticles) {
state.indexArticles = pArticles
state.errors = {}
},
setError (state, errors) {
state.errors = errors
},
resetState (state) {
Object.assign(state, getDefaultState())
}
}
const actions = {
// ...
async fetchIndexArticles ({ commit }) {
try {
const response = await articlesService.fetchIndexArticles()
commit('fetchStart')
commit('setIndexArticles', response.data)
commit('fetchEnd')
return response
} catch (error) {
commit('setError', error)
this._vm.$q.loading.hide()
}
},
...
}
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
and in my index page:
<script>
import store from '../store/'
export default {
computed: {
indexarticles() {
return this.$store.getters['articles/indexArticles'];
}
},
created() {
this.$store.dispatch('articles/fetchIndexArticles')
.then(() => this.$store.dispatch('videolessons/fetchIndexVideolessons'))
...
.then(() => {
this.isLoading = false;
});
}
};
</script>
<template>...</template>
can you help to correct my store modules?
Thanks
ps:
videolessons.js
const getDefaultState = () => {
return {
indexvideolessons: [],
}
}
const state = getDefaultState()
const getters = {
indexVideolessons (state) {
return state.indexvideolessons
},
}
const mutations = {
setIndexVideolessons (state, pVideolessons) {
state.indexvideolessons = pVideolessons
state.errors = {}
},
}
const actions = {
async fetchIndexVideolessons ({ commit, dispatch }) {
try {
const response = await videolessonsService.fetchIndexVideolessons()
commit('setIndexVideolessons', response.data)
return response
} catch (error) {
commit('setError', error)
}
},
}
export default {
namespaced: true,
state,
getters,
actions,
mutations
}

State is undefined inside of vuex action

I can see from the Vue-DevTools that the playlist state is populated, but when I destructure the state off of the context object in my action, state is undefined...
Here is the relevant code:
import PlaylistService from './api/PlaylistService'
export const state = {
playlist: {},
oldTitle: '',
oldDescription: ''
}
export const actions = {
async edit({ commit, state }, payload) {
try {
console.log(state) // **undefined?!?!**
const updated = await PlaylistService.update(state.playlist.guid, {
title: payload.title,
description: payload.description
})
commit('edit', updated)
} catch (error) {
console.error(error)
}
}
}
export const mutations = {
openEdit(state, payload) {
state.playlist = payload
state.oldTitle = payload.title
state.oldDescription = payload.description
},
edit(state, payload) {
state.playlist = payload
},
cancelEdit(state) {
state.playlist.title = state.oldTitle
state.playlist.description = state.oldDescription
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
Here is the Vuex state tree from the dev tools:
And then I click a save button to do a patch request, and the console.log(state) in the above action gives undefined.
I don't know how to fix that. Any help is appreciated. Thanks.
Well, Remove export from state, actions & mutation as you're already exporting them in the end with export default.
const state = {
playlist: {},
oldTitle: '',
oldDescription: ''
}
const actions = {
async edit({ commit, state }, payload) {
try {
console.log(state) // **undefined?!?!**
const updated = await PlaylistService.update(state.playlist.guid, {
title: payload.title,
description: payload.description
})
commit('edit', updated)
} catch (error) {
console.error(error)
}
}
}
const mutations = {
openEdit(state, payload) {
state.playlist = payload
state.oldTitle = payload.title
state.oldDescription = payload.description
},
edit(state, payload) {
state.playlist = payload
},
cancelEdit(state) {
state.playlist.title = state.oldTitle
state.playlist.description = state.oldDescription
}
}
Hope this helps!

Using methods on vuex getter

I am trying to do a .find() method on a Vuex getter.
However when I do so, it gives me the following error:
Uncaught TypeError: ur.find is not a function
I have followed the docs and I cannot seem to understand why I cannot do methods like .find() or .forEach() on the user-Object provided by the vuex Getter.
Am I doing something wrong, or is this type of thinking out of the scope?
This is an example of my mixin auth.js
export const auth = {
methods: {
y(r){
const ur = this.$store.getters.getUserRoles;
console.log(ur); // Returns {__ob__: Observer}...
ur.find( uRole => { // ur.find is not a function
return uRole === r
})
}
}
};
And this is my Vuex instance from the main vue; app.js
const store = new Vuex.Store({
state: {
user: {}
},
mutations: {
setUser (state, data) {
state.user = data;
},
},
getters: {
getUserRoles(state){
return state.user.roles;
}
},
actions: {
getUser ({commit}) {
axios.get('/api/user').then(response => {
const data = response.data.data;
commit('setUser', data);
});
}
}
});
The response from /api/user:
{
admin: true,
projectManager: false,
timeAdmin: false
}