vue.js move method from .vue to vuex store - vuejs2

Scenario:
in user.js I have:
import * as mutationTypes from "../mutation-types";
import {user} from "./user_data";
export const state = {
user: user
...
}
export const getters = {
user: (state) => state.user,
...
};
export const mutations = {
[mutationTypes.SET_USER]: (state, payload) => {
state.user=payload;
},
...
);
export const actions = {
setUser: ({ commit }, payload) => {
commit(mutationTypes.SET_USER, payload);
},
...
);
export default {
state,
getters,
mutations,
actions,
};
now I want to move a method used in several pages from the .vue pages to this store page:
so I added to user.js actions the following:
getUser: async ({ commit }) =>{
this.user.loading=true;
try{
const res = await this.$http.post('/ajax/settings/settings_read.php');
if (res.data.errorid=='0')
{
let payload=res.data.user;
commit(mutationTypes.SET_USER, payload);
}
else
{
this.$router.push('/auth/login').catch(() => {});
}
} catch(e)
{
console.log(e);
}
this.user.loading=false;
},
and in .vue pages (actually I tried may different solutions adding async/await in several places)
import { mapActions } from "vuex";
...
created(){
this.$store.dispatch("getUser");
},
but does not work.
Can suggest the right way to move a method to vuex store?

Looks like this.user is reference to user in your state, hence
this.user.loading=true;
would change the state outside the mutation.

Related

Vuex action not works with namespaced inside Nuxt fetch

I am building my own small project. When i try to access states from main store (index.js) inside of nuxt fetch method all works fine, but while i am trying to access from namespaced(store/photos.js) store it wont work. Here is my code.
store/index.js ( Works )
export const state = () => ({
fetchedData: []
})
export const mutations = {
setData: (state, data) => {
state.fetchedData = data;
}
}
export const actions = {
async get(vuexContext) {
const requestedData = await this.$axios.get("https://jsonplaceholder.typicode.com/users");
vuexContext.commit('setData', requestedData.data);
},
}
my Component:
<script>
import { mapState, mapActions } from 'vuex'
export default {
async fetch({ error,store })
{
try {
await store.dispatch('get');
} catch (error) {
console.log(error);
}
},
computed: {
...mapState(['fetchedData'])
}
};
</script>
store/photos.js ( Does not works )
export const state = () => ({
list: []
});
export const mutations = {
setPhotos(state, data) {
state.list = data;
}
};
export const actions = {
async getPhotos(vuexContext, context) {
const requestedData = await this.$axios.get(
"https://jsonplaceholder.typicode.com/photos"
);
vuexContext.commit("setPhotos", requestedData.data);
}
};
Same Component but modified
<script>
import { mapState, mapActions } from 'vuex'
export default {
async fetch({ error,store })
{
try {
await store.dispatch('photos/getPhotos');
} catch (error) {
console.log(error);
}
},
computed: {
...mapState({
list : 'photos/list'
})
}
};
</script>
Thanks in advance.
namespaced: true,
You can add this to your index.js file. Hope this will work.
Reference link:
Try this

Axios - get data from api in vuex actions?

How to correctly transfer or rewrite the function in actions that will receive the first photo from each album in?
my photos models:
import { api } from "#/apis/config";
const endPoint = 'photos'
const state = {
photos: []
}
const getters = {}
const mutations = {
SET_PHOTOS(state, data) {
state.photos = data
}
}
const actions = {
loadMore(id) {
api.get(`photos?albumId=${id}`).then(response => {
return response.data[0].thumbnailUrl;
});
}
}
export default {
namespaced: true,
state,
getters,
actions,
mutations
};
And my album component:
...
<script>
import {mapActions} from "vuex";
export default {
name: "GridAlbums",
props: ['album'],
data() {
return {
loading: true,
errored: false,
photo: null
}
},
mounted() {
this.photo = this.loadMore(this.album.id)
},
methods: {
...mapActions("photos", ["loadMore"])
}
}
</script>
...
Here is my configuration file for api, where VUE_APP_HOST is https://jsonplaceholder.typicode.com/
import axios from 'axios'
export const api = axios.create({
baseURL: process.env.VUE_APP_HOST,
})
api.interceptors.response.use(
response => {
return response
},
error => {
return Promise.reject(error)
}
)
If you get the data this way, then everything turns out as it should:
Try adding async / await in vuex actions, because actions must be asynchronous and store and mutations synchronous.
Also use try / catch instead Promise that way you keep your code cleaner

Vuex data just show once then won't display after reloading

why my json data display just only once and after reloading the page it won't show again.
Did I miss something here?
import axios from "axios";
const store = {
careers: []
};
const getters = {
allCareers: (state) => state.careers
};
const mutations = {
RETRIEVE_CAREERS: (state, career) => (state.careers = career),
};
const actions = {
async careers({ commit }) {
try {
const response = await axios.get('http://localhost:9001/career/jobs/');
commit('RETRIEVE_CAREERS', response.data);
} catch (err) {
console.log(err);
}
},
};
export default {
store,
getters,
mutations,
actions
}
and in my component I do this:
import { mapActions, mapGetters } from "vuex";
export default {
computed: {
...mapGetters([
"allCareers"
/* more getters here if necessary */
])
},
methods: {
...mapActions(["careers"])
},
created() {
this.careers();
}
};
and in template I just do this:
<template>
<section>
<v-card>
{{allCareers}}
</v-card>
</section>
</template>
Why it will show only once but won't show after reloading the page?
I don't see anywhere that you "persist" the fetched data. Vuex does not persist the data across reloads, it acts as an in-memory storage
You still have to persist your data to local storage of some sorts like localStorage or indexedDB.
Here is a simple solution:
const store = {
careers: JSON.parse(localStorage.getItem('careers') || '[]');
};
const mutations = {
RETRIEVE_CAREERS: (state, career) => {
state.careers = career;
localStorage.setItem('careers', JSON.stringify(career));
}
};

vuex unknown action (or mutation) type

I'm writing a simple code to set token in store in an Nuxt application. when I tried to call a mutation or action from my store, this error is logged in console: [vuex] unknown action type: setToken
import Vuex from 'vuex';
export const store = new Vuex.Store({
state:()=> ({
token: ''
}),
getters: {
getToken: state => {
return state.token;
}
},
mutations: {
setToken: (tokenStr) => {
state.token = tokenStr;
}
},
actions: {
setToken: ({ commit }, tokenStr) => {
commit('setToken', tokenStr);
}
}
})
This is a method trying to call the mutation:
methods:{
setToken(){
this.$store.dispatch('setToken','token1');
this.token = this.$store.getters.token;
}
}
You are using the 'classic' and now deprecated method of setting the vuex store in nuxt. You should set it up like this:
// store/index.js
export const state = () => ({
token: ''
})
export const mutations = {
SET_TOKEN (state, tokenStr) {
state.token = tokenStr
}
export const actions = {
setToken ({ commit }, tokenStr) {
commit('SET_TOKEN', tokenStr)
}
}
export const getters = {
token: (state) => state.token
}
Nuxt will build the store for you from there. You can see it in the doc here.
You can dispatch actions in components with this.$store.dispatch('xxx'), or use the mapActions helper which maps component methods to store.dispatch calls (requires root store injection):
Try Another Method For Dispatching An Action
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment',
// map `this.increment()` to
this.$store.dispatch('increment')
// `mapActions` also supports payloads:
'incrementBy' // map `this.incrementBy(amount)` to `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // map `this.add()` to `this.$store.dispatch('increment')`
})
}
}

vuex store getters not working in a component

Can anyone see why this wouldn't work please,
Trying to use vuex store to manage my axios requests and transfer to a component as follows:
In my vuex store module I have the following
import axios from "axios";
export const state = () => ({
cases: [],
})
export const mutations = {
listCases (state, cases) {
state.cases = cases;
},
}
export const actions = {
loadCases ({ commit, context }) {
return axios.get('http')
.then(res => {
const convertCases = []
for (const key in res.data) {
convertCases.push({ ...res.data[key], id: key })
}
commit('listCases', convertCases)
})
.catch(e => context.error(e));
},
export const getters = {
// return the state
cases(state) {
return state.cases
}
}
I checked amd my axios request is returning my results as expected and passing to the mutation
In my component I have
import { mapMutations, mapGetters, mapActions } from 'vuex'
export default {
created () {
this.$store.dispatch('cases/loadCases');
},
computed: {
...mapGetters ({
cases: 'cases/cases'
})
},
</script>
Now i assumed based on what I've learnt that i could call with
and this would return my items.
but i get an error cases is not defined,
Anyone abe to tell me my error please
Many Thanks
Take a look here: https://v2.vuejs.org/v2/guide/list.html#Array-Change-Detection
You may be able to make it reactive this way:
export const mutations = {
listCases (state, cases) {
state.cases = [];
cases.forEach((c) => {
state.cases.push(c);
});
},
}