Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the right way to make API calls with Vuex?

I have a Vue Webpack app with Vuex (I am new to both, coming in from the Ember world). I've currently got it setup to use vue-resource with two files like this:

/src/store/api.js

import Vue from 'vue';
import { store } from './store';

export default {
  get(url, request) {
    return Vue.http
      .get(store.state.apiBaseUrl + url, request)
      .then(response => Promise.resolve(response.body))
      .catch(error => Promise.reject(error));
  },
  post(url, request) {
    return Vue.http
      .post(store.state.apiBaseUrl + url, request)
      .then(response => Promise.resolve(response))
      .catch(error => Promise.reject(error));
  },
  // Other HTTP methods removed for simplicity
};

I then import the api.js file above into my /src/store/store.js file like this:

import Vue from 'vue';
import Vuex from 'vuex';
import Api from './api';

Vue.use(Vuex);

// eslint-disable-next-line
export const store = new Vuex.Store({
  state: {
    apiBaseUrl: 'https://apis.myapp.com/v1',
    authenticatedUser: null,
  },

  mutations: {
    /**
     * Updates a specific property in the store
     * @param {object} state The store's state
     * @param {object} data An object containing the property and value
     */
    updateProperty: (state, data) => {
      state[data.property] = data.value;
    },
  },

  actions: {
    usersCreate: (context, data) => {
      Api.post('/users', data)
        .then(response => context.commit('updateProperty', { property: 'authenticatedUser', value: response.body }))
        // eslint-disable-next-line
        .catch(error => console.error(error));
    },
  },
});

When I need to create a new user, I simply this.$store.dispatch('usersCreate', { // my data }); in my component. This works just fine but I have a few issues:

  1. I can't capture issues in the component to show toast messages etc. I can't even check if the AJAX call went through successfully.
  2. If I have a lot of APIs, I'll have to write a lot of actions in my store.js file which is not ideal. I could of course create a standard action that accepts the HTTP method, URL etc. and just call that but I am not sure if this is a good practice.

What is the right way to go about it? How can I check for the AJAX failure / success state in the component where I dispatch the action? What is the best practice to make API calls when using Vuex?

like image 751
JackH Avatar asked Jan 29 '18 15:01

JackH


People also ask

Is pinia better than Vuex?

Pinia has a Simpler API than Vuex Pinia's API is simpler and more intuitive than Vuex. Getting started with state management is much easier even for a junior developer as a lot of boilerplate code that needed to be written between every state change in Vuex has now been removed in Pinia.

What is VueJS API?

VueJS has introduced a new API named Composition API with the Vue 3 update that helps developers reuse components, structure code base, and many more. Modern front-end frameworks like React, Angular and Vue, encourage developers to reuse components.


1 Answers

Your action should return a Promise. Your current code just calls Api.post without returning it, so Vuex is out of the loop. See the example from Vuex docs for Composing Actions.

When you a return a Promise, the action caller can then follow the then() chain:

this.$store.dispatch('usersCreate').then(() => {
  // API success
}).catch(() => {
  // API fail
});

As for organizing your actions, you don't have to put them all in your store.js file. Vuex supports modules/namespacing. https://vuex.vuejs.org/en/modules.html

like image 70
Matt Avatar answered Oct 19 '22 16:10

Matt