Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inject axios into store instance #26

Closed
alidcast opened this issue Jun 11, 2017 · 19 comments
Closed

Inject axios into store instance #26

alidcast opened this issue Jun 11, 2017 · 19 comments

Comments

@alidcast
Copy link

alidcast commented Jun 11, 2017

Is there no way to inject or import the configured axios module into the store instance? Having to pass it as an additional argument to the store action doesn't feel right and really limits usage.

This feature request is available on Nuxt.js community (#c6)
@pi0
Copy link
Member

pi0 commented Jun 11, 2017

Hi @alidcastano . Actually i was and still trying to find a better way for usage in actions. But unfortunately it is not possible as vuex internally handles dispatch/commits. I will investigate more on possible solutions.

@alidcast
Copy link
Author

I ended up doing this, which actually isn't a terrible way to do it:

// component 
export default {
 methods: {
  login () {
    this.$store.dispatch('auth/login', {
      post: this.$axios.post,
      username: this.formUsername,
      password: this.formPassword
    })
  }
} 
// store/auth.js
export const actions = {
  login ({ commit }, { post, username, password }) {
    post('/auth/login', { username, password })
  }
}

@pi0
Copy link
Member

pi0 commented Jun 11, 2017

Agree terrible state :)) I'm trying to use vuex plugins (https://vuex.vuejs.org/en/plugins.html) injecting on every action.

@alidcast
Copy link
Author

Are you referring to the nuxt auth module?

@pi0
Copy link
Member

pi0 commented Jun 11, 2017

Not necessary auth module. There should be a common solution for that :))

@benosman
Copy link

benosman commented Jul 6, 2017

@pi0: Is there any progress with this, or other suggestions on how to achieve it? This module is so close to what I need!

I need axios access throughout my vuex stores and would rather not pass through the instance into the action.

@benosman
Copy link

benosman commented Jul 7, 2017

I've been experimenting with vuex plugins as mentioned earlier in the issue by @pi0.
At first they didn't seem to be suitable as they are called only after mutators (not actions).

However, when setting up the plugin one does have access to the store object. So I experimented with the following with some success. (it does seem hackish though)

Updated
in ~/store/index.js

function axiosInjectPlugin() {
  return store => {
    store.getters['$axios'] = () => {
      return store.$axios
    }
  }
}

export const plugins = [
  axiosInjectPlugin()
]

export const actions = {
  // for standard stores, use getters
  login (ctx, { username, password, role}) {
    let $axios = ctx.getters['$axios']()
  }
  // for module based stores, use rootGetters
  login2 (ctx, { username, password, role}) {
    let $axios = ctx.rootGetters['$axios']()   
  }
}

A couple of notes:

  • I injected the entire store object itself rather than just axios, in my initial testing the $axios object wasn't fully instantiated at that point. This could be circumvented with a function instead. (this was causing peformance issues as expected.

  • I injected a function to return the $axios object, I need to find out how to properly inject a dynamic getter so there is no need to call the function.

  • I used getters to store it as I didn't want to mess with state.

  • I stored it only in the root of the store, I didn't want to pollute the getters list by adding one for each store module.

Any suggestions on how to make this less hackish? Will this approach cause problems with SSR in runInNewContext ?

@pi0
Copy link
Member

pi0 commented Jul 7, 2017

@benosman Pretty tricky approach :D But I think it would lead to potential performance problems and usage is little complicated. I'm investigating for other solutions too will make this thread updated.

@benosman
Copy link

benosman commented Jul 7, 2017

@pi0 - yes, injecting the store itself was causing some issues as expected.

I've changed it now to a function that returns the $axios object, but still the usage is complicated unfortunately.

Look forward to seeing your solutions on here :)

@benosman
Copy link

benosman commented Jul 9, 2017

I've continued to have a look at this, mainly as I wanted to learn a bit more how vuex works.

In the end I found a way to replace the action handlers with one that contains an $axios parameter. I used a store plugin for this case, as it makes it optional.

I've created a gist for the plugin here, as I wasn't sure where/how it would fit inside this nuxt module.
https://gist.github.com/benosman/350196da44933bff26789ee64651e4af

I tried to keep the amount of code brought in from vuex to a minimum, but there is more than i'd like because the key functions are not accessible at runtime.

There was talk of a similar issue about adding extra context on this vuex pull request, but work on that seems to have stopped for now.
vuejs/vuex#571

@pi0
Copy link
Member

pi0 commented Jul 9, 2017

@benosman I think we had found a workaround it is on the way into nuxt core :) Hold on a little more :)) PS: Learning by reading source is great keep it going :)

@benosman
Copy link

benosman commented Jul 9, 2017

Cool , do you have a link to the related workaround in nuxt core?

Right now, my approach seems to work so I can start building out my store modules using axios, then I will switch over when the workaround arrives.

@uptownhr
Copy link
Contributor

@pi0 can you give a high level description of what the work around will mean from a user stand point? Will this mean axios will not need to be sent with each dispatch?

@pi0
Copy link
Member

pi0 commented Jul 27, 2017

@uptownhr After this enhancement releases, we can access entire store instance inside actions and mutations. So using axios would be as easy as:

actions: {

  async editPost ({ commit }, { type, id }) {
     // We can use this.$axios which `this` refers to current store
     await this.$axios.post(`/posts/${id}`)
  }

}

@uptownhr
Copy link
Contributor

@pi0 that is wonderful. I've been holding off on upgrading due to this :)

@pi0
Copy link
Member

pi0 commented Aug 29, 2017

Finally is available with [email protected] 🍸 Will be shipped with nuxt rc8. For earlier testing, the only required thing is yarn add vuex to install latest version. Then you can directly use axios like this:

export default {
  actions: {
    getProfile() {
       const profile = await this.axios.$get('user/profile')
    }
  }
}

@MRZMUH001
Copy link

Is this still not available in nuxt rc11?!

@pi0
Copy link
Member

pi0 commented Dec 21, 2017

@MRZMUH1001 Yes it's already available :) Refer to the docs for usage.

@jeck5895
Copy link

Hi I can't find to work with nuxt-axios in my store which actions is separated in a different file actions.js
export default{ fetchCities: ({commit}, payload) => { return new Promise ((resolve, reject) => { this.$axios.get('/web/cities') .then(response => { commit('setCities', response.data); resolve(response) }) .catch(err => { console.log(err) reject(err); }) }) }, }

Can u help me what's the problem?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants