Nuxt.js - The best place for API calls
Asked Answered
A

4

15

I'm new to Vue.js Nuxt and all front-end stuff.

I have a question about API calls. I'm not sure what is the right way, the best practice here.

I have a store. In that store, I have actions that are calling my API and sets state eg.

async fetchArticle({ state, commit }, uuid) {
    const response = await this.$axios.get(`articles/${uuid}/`)
    commit('SET_ARTICLE', response.data)
},

And that is fine it is working for one component.

But what if I want to just fetch the article and not changing the state.

To be DRY first thing that comes to my mind is to create the service layer that is fetching the data and is used where it is needed.

Is it the right approach? Where can I find some real-world examples that I can take inspiration from?

Ardis answered 1/9, 2020 at 17:59 Comment(0)
F
18

Using the repository pattern to abstract your API is definitely a good idea! Whether you use the @nuxtjs/axios module or the @nuxt/http module, you can pass either instance to your repository class/function. Below a real world example of an abstracted "repository.js" file.

export default $axios => resource => ({
  index() {
    return $axios.$get(`/${resource}`)
  },

  create(payload) {
    return $axios.$post(`/${resource}`, payload)
  },

  show(id) {
    return $axios.$get(`/${resource}/${id}`)
  },


  update(payload, id) {
    return $axios.$put(`/${resource}/${id}`, payload)
  },

  delete(id) {
    return $axios.$delete(`/${resource}/${id}`)
  }

})

You can then create a plugin to initialize all different kinds of repositories for your endpoints:

import createRepository from '~/path/to/repository.js'

export default (ctx, inject) => {
  const repositoryWithAxios = createRepository(ctx.$axios)

  const repositories = {
    posts: repositoryWithAxios('posts'),
    users: repositoryWithAxios('users')
    //...
  }

  inject('repositories', repositories)
}

Further read: Organize and decouple your API calls in Nuxt.js

Frasquito answered 2/9, 2020 at 7:36 Comment(2)
Now if we register that repositories file in the plugin array in nuxt.config.js, then isn't a bad practice? Because in that way, it will be imported to each vue component, however, each repo should be imported where is required. I'm thinking in terms of memory optimization.Goodwife
I had asked the same thing as a separate question here #70185504Goodwife
W
7

I will an example of a service layer implementation for my portfolio to create my dashboard that shows some statics about my github and stackoverflow profiles, to do this i created a folder called services inside the project root :

pages
services
  |_AxiosConfig.js
  |_GitHubService.js
  |_StackoverflowService.js
   ...

in the AxiosConfig.js file i put i created an axios instance with its configuration :

import axios from 'axios';

const clientAPI = url =>
  axios.create({
    baseURL: url,
    withCredentials: false,
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
   
  });

export default clientAPI;

then in my GitHubService.js i imported that axios instance called clientAPI which i used to my requests :

import clientAPI from './AxiosConfig';

const baseURL = 'https://api.github.com';
export default {
  getUser(name) {
    return clientAPI(baseURL).get('/users/' + name);
  },
  getRepos(name){
    return clientAPI(baseURL).get('/users/' + name+'/repos');

  },
  getEvents(name,page){

    return clientAPI(baseURL).get('/users/' + name+'/events?per_page=100&page='+page);

  },
  getLastYearCommits(name,repo){

    return clientAPI(baseURL).get('/repos/' + name+'/'+repo+'/stats/commit_activity');

  }

};

then in my page i used asyncData hook to fetch my data :

import GitHubService from '../../services/GitHubService'

export default {
 ...
  async asyncData({ error }) {
    try {
      const { data } = await GitHubService.getUser("boussadjra");
      const resRepos = await GitHubService.getRepos("boussadjra");
      return {
        user: data,
        repos: resRepos.data
      };
    } catch (e) {
      error({
        statusCode: 503,
        message: "We cannot find the user"
      });
    }
  }
Washtub answered 1/9, 2020 at 18:19 Comment(1)
Thanks for your replay. In the end, I used a similar approach but also utilizing the power of plugins in nuxt dynamically injecting the $axios instance.Ardis
M
1

I wanted to use axios in my service/service.js file, so instead of passing axios, I accessed it directly like this:

export default {
  async fetchArticle() {
    let response = await $nuxt.$axios.$get('/api-url')
    return response
  },
}
Meteorite answered 29/10, 2021 at 18:31 Comment(0)
T
0

In Nuxt, if you want to just get the data without keeping it in your store, you could use the asyncData function, which asynchronously loads data (from API calls and the like) and pushes it into the component's data object before rendering.

Talithatalk answered 1/9, 2020 at 18:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.