I am struggling with finding answer for where to ideally put API calls in vue modules. I am not building an SPA. For example my auth block has several components for login, password reset, account verifiction etc. Each block uses axios for API calls. Axios already provides promises, which are async.
The question is about the best pracitces. Do API calls belong in a Vuex actions? Are there any pros/cons of such approach?
Is there any drawback of keeping axios calls within the components they belong to?
Both of these could do the work of Vuex, but they aren't enough to replace Vuex completely. Let's take a look at why Vuex is is still necessary, even in Vue 3. First, Vuex offers advanced debugging capabilities that Vue 3 features does not.
Vue is a progressive Javascript framework and Vuex is the state management tool. We can use redux or flux inside Vue, But Vuex is native to the Vue.
Dispatch triggers an action whereas commit triggers a mutation. $dispatch is always used from your methods in routes/components. It sends a message to Vuex store to perform some action. The action can be performed any time after the current tick so that it will not affect the frontend performance.
I do API calls in services, not Vuex or components. Basically, mixing the API calls in with the store code is a bit too multi-responsibility, and components should be about providing for the view not fetching data.
As an example of a simple service (using Vue.http but same for an Axios call),
FileService .js
import Vue from 'vue'
export default {
getFileList () {
return Vue.http.get('filelist.txt')
.then(response => {
// massage the response here
return filelist;
})
.catch(err => console.error('getFileList() failed', err) )
},
}
I use it in another service as below (the number of layers is up to you).
Note, the outer service is checking the store to see if the fetch already happened.
DataService.js
import FileService from './file.service'
checkFiles (page) {
const files = store.state.pages.files[page]
if (!files || !files.length) {
return store.dispatch('waitForFetch', {
resource: 'files/' + page,
fetch: () => FileService.getFileList(),
})
} else {
return Promise.resolve() // eslint-disable-line no-undef
}
},
waitForFetch
is an action that invokes the fetch function passed in to it (as provided by FileService). It basically provides wrapper services to the fetch, like timeout and dispatching success and failure actions depending on the outcome.
The component never knows about the API result (although it may initiate it), it just waits on data to appear in the store.
As for drawback of just calling the API in the component, it depends on testability, app complexity. and team size.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With