1
votes

I am getting an error of "[Vue warn]: Error in v-on handler: "TypeError: Cannot read property 'mutate' of undefined" when trying to make an Vue-Apollo/GraphQL mutation query. The method is:

    ...mapMutations(['signIn']),
    handleSignUp() {
      signUp({
        apollo: this.$apollo,
        ...this.form,
      }).then(response => _get(response, 'data.registerUser', {}))
      .then(response => {
        if(response.success) {
          const user = response.user;
          this.signIn(user); // using the Vuex store
          localStorage.setItem(AUTH_TOKEN_KEY, user.authenticationToken);
          this.$router.push({ name: 'home' });
        } else {
          this.errors = this.errorMessages(response.data.registerUser.errors);
        }
      }).catch(error => {
        this.errors = [error];
      });
    }

The registerUser method is being imported by:


import gql from 'graphql-tag'

const mutation = gql`
  mutation registerUser(
    $email: String!,
    $password: String!,
  ) {
    registerUser(input: {
      email: $email,
      password: $password,
    }) {
      user {
        id
        email
        authenticationToken
      }
      success
      errors
    }
  }
`;

export default function signUp({
    apollo,
    email,
    password,
}) {
    return apollo.mutate({
        mutation,
        variables: {
            email,
            password,
        },
    });
}

My apolloProvider file is:

import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { ApolloClient } from 'apollo-client';
import { createHttpLink } from 'apollo-link-http';
import { setContext } from 'apollo-link-context';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { AUTH_TOKEN_KEY } from './appConstants';

Vue.use(VueApollo);

const host = window.location.origin;
const httpLink = createHttpLink({ uri: `${host}/graphql` });

const authLink = setContext((_, { headers }) => {
  // get the csrfToken from the element in appilcation.html layout
  const csrfToken = document.
    querySelector('meta[name="csrf-token"]').
    attributes.content.value;

  // get the authentication token from local storage if it exists
  const authToken = localStorage.getItem(AUTH_TOKEN_KEY);

  return {
    headers: {
      ...headers,
      'X-CSRF-Token': csrfToken,
      authorization: authToken ? `Bearer ${authToken}` : '',
    },
  };
});

const client = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache(),
});

const apolloProvider = new VueApollo({ defaultClient: client });

export default apolloProvider;

My Vue pack is:

import Vue from 'vue/dist/vue.esm'
import LandingApp from '../components/landing/LandingApp.vue'
import apolloProvider from './configuration/apolloProvider'
import Vuex from 'vuex'
import createStore from 'store/baseStore.js'

Vue.use(Vuex)

document.addEventListener('DOMContentLoaded', () => {
  new Vue({
    el: '#landing',
    apolloProvider,
    store: createStore(),
    components: { LandingApp }
  })
})

Apollo seems to not be initiating. It is unable to call mutate on undefined. No idea what I'm missing here.

edit: I am following this guide - https://technology.doximity.com/articles/token-authentication-with-rails-vue-graphql-and-devise

1
In handleSignUp, where does signUp come from?Phil
I import it from a file. I pasted the wrong file (signIn, as opposed to SignUp) by mistake. I edited with the correct file and code.FoolishGamesDev
Fwiw, I get the same undefined method from trying to sign in as well. It seems apollo is undefined all across the vue app.FoolishGamesDev
Right, so the only reason this would fail is if this.$apollo is undefined in your component. Everything looks ok so far. Have you tried checking the Vue Apollo issues list?Phil
I've looked through and haven't seen anything. I've tried renaming the constant, the default export as someone else had noted in a thread. No dice. this.$apollo is undefined for me on a console.logFoolishGamesDev

1 Answers

0
votes

Moving all the code from the apolloProvider file into my Vue pack fixed the undefined issue. Not sure why, but for now at least it is hitting the back end.