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
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
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
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));
}
};
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')`
})
}
}
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);
});
},
}