September 27, 2016

Use Apollo in your VueJS app

Guillaume Chau

Guillaume Chau

Editor’s note: This post is from Guillaume Chau, an Apollo contributor who built an integration package between VueJS and Apollo. Check it out and contribute to it here!

As you may know, the Apollo team has built a great GraphQL client and tooling that makes it easy to use data from your server in any JavaScript app. Why not use it with another amazing technology like VueJS?

Now you can do just that with vue-apollo, an npm package I wrote that allows you to write GraphQL queries in your VueJS components while using Apollo under the hood.

Use it in your VueJS app

First, install these packages in your project folder:

npm install — save apollo-client vue-apollo

Then, you need to create an Apollo client and install the vue-apollo plugin into VueJS:

import Vue from 'vue';
import App from './App.vue';
import ApolloClient, { createNetworkInterface, addTypename } from 'apollo-client';
import VueApollo from 'vue-apollo';

// Create the apollo client
const apolloClient = new ApolloClient({
  networkInterface: createNetworkInterface({
    uri: 'http://localhost:8080/graphql',
    transportBatching: true,
  }),
  queryTransformer: addTypename,
  dataIdFromObject: r => r.id,
});

// Install the vue plugin
// With the apollo client instance
Vue.use(VueApollo, {
  apolloClient,
});

// Start the Vue app
new Vue({
  el: '#app',
  render: h => h(App)
});

Fetch data with GraphQL queries

You can now use Apollo directly in your components to query your GraphQL server. Inside a component, the Apollo client can be accessed with ‘this.$apollo’:

<script>
export default {
  created() {
    this.$apollo.watchQuery({
      /* options */
    }).then(data => {
      console.log(data);
    });
  },
};
</script>

But the preferred way to make queries is to declare them with the ‘apollo’ option in the component definition:

<script>
import gql from 'graphql-tag';
// GraphQL query
const postsQuery = gql`
  query allPosts {
    posts {
      id
      title
      votes
      author {
        id
        firstName
        lastName
      }
    }
  }
`;
// Vue component definition
export default {
  // Local state
  data: () => ({
    // You can initialize the 'posts' data here
    posts: [],
    loading: 0,
  }),
  // Apollo GraphQL
  apollo: {
    // Local state 'posts' data will be updated
    // by the GraphQL query result
    posts: {
      // GraphQL query
      query: postsQuery,
      // Will update the 'loading' attribute
      // +1 when a new query is loading
      // -1 when a query is completed
      loadingKey: 'loading',
    },
  },
};
</script>

<template>
  <div class="post-list">
    <!-- If there is one or more queries loading -->
    <template v-if="loading > 0">
      Loading
    </template>
    <!-- Actual view -->
    <template v-else>
      <ul>
        <!-- Post list items -->
        <li v-for="post in posts" :key="post.id">
          {{ post.title }} by
          {{ post.author.firstName }} {{ post.author.lastName }}
        </li>
      </ul>
    </template>
  </div>
</template>

Thanks to the VueJS reactivity system, the ‘posts’ local data will be automatically updated with the GraphQL query result and your DOM updated.

You can initialize the corresponding data attribute in the ‘data’ hook with a default value:


  // Local state
  data: () => ({
    // You can initialize the 'posts' data here
    posts: [],
    loading: 0,
  }),

If you want to update your data automatically when another user changes it, you can poll the server with the ‘pollInterval’ option, specifying an interval duration in milliseconds:


  apollo: {
    posts: {
      query: postsQuery,
      loadingKey: 'loading',
      // Polling query
      pollInterval: 300, // ms
    },
  },

Update your data with GraphQL mutations

In the component methods and hooks, you can use the ‘$apollo’ object to call mutations:

<script>
import gql from 'graphql-tag';
// GraphQL Mutation with one parameter
const upvoteMutation = gql`
  mutation upvotePost($postId: Int!) {
    upvotePost(postId: $postId) {
      id
      votes
    }
  }
`;
export default {
  // Attribute
  props: {
    // Post id passed down to this component
    postId: {
      type: Number,
      required: true,
    },
  },
  methods: {
    upvote() {
      // Mutation
      this.$apollo.mutate({
        mutation: upvoteMutation,
        variables: {
          postId: this.postId,
        },
      }).then(data => {
        console.log('Done upvoting.');
      });
    },
  },
};
</script>

<template>
  <button @click="upvote">Upvote</button>
</template>

In this component, we call the ‘upvotePost’ mutation on the GraphQL server, that returns the updated post data. That way, the Apollo cache is up-to-date, and again, thanks to VueJS reactivity system, your view should reflect the new votes count.


These are just the basics of using Apollo in your VueJS components. The more advanced features in vue-apollo are documented here, and you can take a look at the hello world example to have a better idea of how things work.

Written by

Guillaume Chau

Guillaume Chau

Read more by Guillaume Chau