0
votes

I am building an SPA and I have a couple of different forms that submit data to an API. I am using axios for the ajax calls and have built a wrapper class around it for my use-case, called api. Inside that class I handle errors thrown by that instance.

The problem is I was storing an instance of the api class in each form's state. I later realized that functions shouldn't live in the state due to serialization.

The reasoning behind having the api class in the state was so that all of the children components of a form could access the errors and display their respective error along with removing the error on update.

One solution could be using an axios interceptor and commit all errors to a global errors module. But then I wouldn't know which errors belong to which form, in case two forms (or other requests) were submitted at the same time. I could of course save the errors in regard to the request URI, but then I would also have to take the request method into consideration.

reportError(state, { uri, method, errors }) {
  state.errors[uri + '@' + method] = errors;
}

Then I could have a getter like:

getErrorsByRequest: state => ({ uri, method }) => {
    return ...
}

But this feels unnecessarily awkward.

Since what I am trying to achieve is most likely very common, I am wondering, how do I sanely handle ajax errors reusably with Vuex?

1
You definitely should check this question.Andrew Vasilchuk

1 Answers

1
votes

I was checking for my old projects, and i did something similar:

This is my axios instance interceptor:

axiosInstance.interceptors.response.use(response => response, error => {
  const { status } = error.response
  ...
  ...
  // data invalid (Unprocessable Entity)
  if (status === 422) {
    // errors list from response
    const dataErrors = error.response.data.errors
    let objErrors = {}

    // joining just the first error from array errors as value for each prop
    for (let key in dataErrors) {
      objErrors[key] = dataErrors[key].join()
    }

    // commiting to errors module
    store.commit('errors/SET_ERRORS', objErrors)
  }
  ...
  ...
})

Here my store module errors:

export const state = {
  form_errors: {}
}

export const mutations = {
  SET_ERRORS: (state, errors) => { state.form_errors = errors },

  CLEAN_ERRORS: (state) => { state.form_errors = {} }
}

Using on components:

computed: {
    ...mapState('errors', ['form_errors'])
}

Using on form template:

<q-input
  v-model="form.description"
  :error-message="form_errors.description"
  :error="!!form_errors.description"
/>