R1pairedas
R1pairedas

Reputation: 135

Vuex, best practice with a global errors and notifications handling

here is what i do, and i'am not realy sure its correct :

//store
async addUser({commit}) {
  try {
    const {data} = await apiService.addUser()
    commit('SET_USER', data)
    commit('SET_NOTIFICATION', {type:'success', message: 'user successfuly created'})
  } catch (error) {
    commit('SET_NOTIFICATION', {type:'error', message:error})
  }

}

SET_USER(state, user) {
    state.users.push(user)
}

//my component:
async addUser() {
  this.isLoading = true
  await this.$store.dispatch('updatePatient', this.form)
  this.isLoading = false
}

is it legit ?

sometimes i think i would need more logic inside my component depending on the succes or rejected api request. Should i put all the logic in my actions ? like i do at the moment ?

Maybe should I add a status state for each actions, for example :

state {
  users: []
  postUserSuccess: null
  postUserError: false
  updateUserSuccess: null
  updateUserError: false
  // ...
}

and do what i want in the component with a computed property mapped to the store ?

What do you think ?

Upvotes: 5

Views: 3920

Answers (1)

Larizza Tueros
Larizza Tueros

Reputation: 629

I don't know if it's a best practice but I let the components the exception handling. That method has its pros (you don't have to pollute the state with error management) and cons (you have to repeat the error management code for every action call).

  1. All service calls will be made in actions
  2. The state will only be set in mutations.
  3. All service calls will return a promise with a resolve(data to load in the state) and a reject(message errors to present).
  4. There will be an interceptor to reject the response in case there's a custom error (here you can put if the response has an error prop reject the response and send as an error the error prop, now you don't have to deconstruct the response in the action).

I'm going to give you a simplified example (I use axios, you can learn how to do it with the library that you use).

Actions in Vuex are asynchronous. So you don't need to try/catch them.

ApiService - Add User

const addUser = () => {
    return new Promise((resolve, reject) => {
        axios
            .post(url, user)
            .then(response => resolve(response.data))
            .catch(error => reject(error));
    });
};

store

async addUser({commit}) {
    const data = await apiService.addUser();
    commit('SET_USER', data);
    return data;
}

if the promise in apiService.addUser is resolved the commit is going to be made if is rejected axios will return the promise and you can catch the error in the component that calls the action.

Component

async addUser() {
    this.isLoading = true;
    try {
        await this.$store.dispatch('updatePatient', this.form);    
    } catch (error) {
        // here goes the code to display the error or do x if there is an error, 
        // sometimes I store an errors array in the data of the component other times I do  x logic
    }
    this.isLoading = false;
  }

State Your state will be cleaner now that you don't need to store those errors there.

state {
  users: []
}

Upvotes: 5

Related Questions