Axios - get data from api in vuex actions? - vue.js

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

Related

On component created hook call Action to fetch data from database and store it in state and then call Getter to get the data

So basically I have this component and I am using its created hook to fetch data using vue-resource and VUEX action, storing that data in store and right after that trying to get that data using VUEX getter but I am unable to do so. Any work around or I am doing something wrong. I am new to Vue!
Component:
import { mapActions } from 'vuex';
import { mapGetters } from 'vuex';
export default {
components: {
categoryHeader: CategoryHeader,
categoryFooter: CategoryFooter,
AddCategory
},
data() {
return {
openCatAdd: false,
categories: [],
pagination: []
}
},
methods: {
...mapActions([
'getCategories'
]),
...mapGetters([
'allCategories'
])
},
created() {
this.getCategories(1);
this.categories = this.allCategories();
// console.log(this.categories);
}
};
Store:
import Vue from "vue";
const state = {
categories: [],
};
const mutations = {
setCategories: (state, payload) => {
state.categories = payload;
}
};
const actions = {
getCategories: ({commit}, payload) => {
Vue.http.get('categories?page='+payload)
.then(response => {
return response.json();
})
.then(data => {
commit('setCategories', data.data);
}, error => {
console.log(error);
})
}
}
const getters = {
allCategories: state => {
console.log(state.categories);
return state.categories;
}
};
export default {
state,
mutations,
actions,
getters
};

vue.js move method from .vue to vuex store

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.

vuex: unknown getter: articles

I try to implement vuex modules and understand usage. While trying to import modules in my home.vue, I have found this solution:
import { FETCH_INDEX_ARTICLES } from "#/store/types/actions.type.js";
// imports this => export const FETCH_INDEX_ARTICLES = "fetchIndexArticles"
import { mapGetters, mapActions} from 'vuex'
export default {
name: "Home",
data() {
return {}
},
computed: {
...mapGetters(['articles']),
},
methods: {
...mapActions([FETCH_INDEX_ARTICLES])
}
created() {
this.$store.dispatch(FETCH_INDEX_ARTICLES);
}
};
but instead I get
vuex.esm.js?2f62:438 [vuex] unknown action type: fetchIndexArticles
vuex.esm.js?2f62:950 [vuex] unknown getter: articles
store/index.js
export default new Vuex.Store({
modules: {
articles,
}
});
store/modules/articles.js
const state = {
articles: [],
};
const getters = {
articles(state) {
return state.articles;
},
};
const mutations = {
[SET_ARTICLES] (state, pArticles) {
state.article = pArticles
state.errors = {}
}
}
const actions = {
[FETCH_INDEX_ARTICLES] (context) {
context.commit(FETCH_START)
return ApiService
.get('/articlelist/index/')
.then((data) => {
context.commit(SET_ARTICLES, data.articles);
context.commit(FETCH_END)
})
.catch((response) => {
context.commit(SET_ERROR, response.data.errors);
})
}
};
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
How can I correctly import vuex module?
Thanks
You must specify your modules,
Your way is valid when you import your modules directly into your component
...mapGetters('articles', {
article: 'articles',
})
this.article(2)
https://vuex.vuejs.org/guide/modules.html#binding-helpers-with-namespace
To facilitate the use I use the method dispatch for actions
this.$store.dispatch('articles/FETCH_INDEX_ARTICLES', {anydata})

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