Akryum / vue-cli-plugin-apollo

🚀 @vue/cli plugin for Vue Apollo
https://vue-cli-plugin-apollo.netlify.com/
478 stars 109 forks source link

How to integrate with Vuex #66

Open michaelkornblum opened 5 years ago

michaelkornblum commented 5 years ago

I'm currently trying to fire off a graphQL query from inside Vuex using the apollo plugin. My store.js file looks like this:

import Vue from 'vue';
import Vuex from 'vuex';
import gql from 'graphql-tag';
import { createProvider } from './vue-apollo';

const provider = createProvider();
const { apolloClient } = provider;

Vue.use(Vuex);

export default new Vuex.Store({
  state: {

  },
  mutations: {

  },
  actions: {
    getPosts: () => {
      apolloClient
        .query({
          query: gql`
            query {
              _id
              title
              imageUrl
            }
          `
        })
          .then(data => console.log(data))
          .catch(err => console.error(err))
    }
  },
});

But I keep on getting erors from chrome developer tools stating that it is unable to read the query property of undefined. I know that I am possibly messing this up royally, but what should I import at the top of this file to make it work?

betaSavvy commented 5 years ago

New to this myself but your apolloClient seems to be declared wrongly. I got mine to work as below

instead of

const provider = createProvider();
const { apolloClient } = provider;

try const apolloClient = createProvider().defaultClient;

TitanFighter commented 5 years ago

@betaSavvy , thanks, it works.

I have a question: could you advise, is there any reason to create provider multiply times like shown below

import { createProvider } from './vue-apollo'
const apolloClient = createProvider().defaultClient

in different parts of project (for example, vuex + different components) instead of to call/create const creatED_Provider = createProvider() or const apolloClient = createProvider().defaultClient just once and export creatED_Provider or apolloClient accordingly?

betaSavvy commented 5 years ago

@betaSavvy , thanks, it works.

I have a question: could you advise, is there any reason to create provider multiply times like shown below

import { createProvider } from './vue-apollo'
const apolloClient = createProvider().defaultClient

in different parts of project (for example, vuex + different components) instead of to call/create const creatED_Provider = createProvider() or const apolloClient = createProvider().defaultClient just once and export creatED_Provider or apolloClient accordingly?

I am quite new to all this as well so I would also like to know the answer. All I know is using this plugin means a lot of stuff are being abstracted away and can be difficult for newbie like us to figure out things that need more customised configuration. I normally re-read the documentation to find a solution for my problems but some details are still very vague to be helpful.

Akryum commented 5 years ago

You should call createProvider only once.

TitanFighter commented 5 years ago

yes, and we call it in main.js

new Vue({
  router,
  store,
  apolloProvider: createProvider(),
  render: h => h(App)
}).$mount('#app')

and we can not use something like this.$apollo inside vuex.

So, we need to call craeteProvider at least twice. The first one in main.js and one more time somewhere in vuex. In my case I have a global store and there I have

import { createProvider } from '@/vue-apollo'
const apolloClient = createProvider().defaultClient

const globalState = {
  apolloClient: apolloClient,
  ...
}

export default globalState()

@Akryum is there a better way?

Akryum commented 5 years ago
// apollo-provider.js
export const apolloProvider = createProvider()
import { apolloProvider } from './apollo-provider.js'

new Vue({
  router,
  store,
  apolloProvider,
  render: h => h(App)
}).$mount('#app')
TitanFighter commented 5 years ago

Agree, but then it means that default template in vue-cli-plugin-apollo is not optimal.

vue-apollo.js

// Call this in the Vue app file
export function createProvider (options = {}) {
  // Create apollo client
  const { apolloClient, wsClient } = createApolloClient({
    ...defaultOptions,
    ...options
  })
  apolloClient.wsClient = wsClient

  // Create vue apollo provider
  const apolloProvider = new VueApollo({
    defaultClient: apolloClient,
    defaultOptions: {
      $query: {
        // fetchPolicy: 'cache-and-network',
      }
    },
    errorHandler (error) {
      // eslint-disable-next-line no-console
      console.log('%cError', 'background: red; color: white; padding: 2px 4px; border-radius: 3px; font-weight: bold;', error.message)
    }
  })

  return apolloProvider
}

Would it be better to export created provider instead of a function? If so, than the default vue-apollo.js template and a doc here should be slightly changed.

Akryum commented 5 years ago

No, because it's still useful for SSR.

jeissler commented 5 years ago

@Akryum How would I go about combining the 2 approaches (SSR & Vuex)? So I realized beforehand that I could export a const instead of a function thereby loosing the optional config object I will need on the server side... This leaves me at a crossroads where I must choose one or the other approach unless I'm misunderstanding something in the last few comments on this issue. Thanks for all you hard work on vue-apollo/plugins and in advance for any further insights you can provide!