GraphQL & Vue Composition API with Apollo-Composable
Tags: vue, graphql, javascript, tutorial
Published: 2020-04-13 15:09:52

####[🔆Click Here for Ionic Framework ReactJS and VueJS Tips/Tutorials?🔆](https://buff.ly/35bAMIf) 

In this post we are assuming you understand the basics of GraphQL, but are interested in how to use the [Vue Composition API](https://github.com/vuejs/composition-api) with [GraphQL](https://graphql.org/) in VueJS

>**About GraphQL:** This is one of the best places to start to get complete overview of GraphQL [The Fullstack Tutorial for GraphQL](https://www.howtographql.com/). 

 
###Quickly Spinning Up A GraphQL Server
For this to be helpful, you need a graphql server to work with. In the past, that was always a challenge until I found this great package for quickly spinning up a local server, with data based on a json file/

>[See Documentation for json-graphql-server](https://github.com/marmelab/json-graphql-server)

```sh
npm install -g json-graphql-server
```

```javascript
// db.js - in project root directory
module.exports = {
    posts: [
        { id: 1, title: "Lorem Ipsum", views: 254, user_id: 123 },
        { id: 2, title: "Sic Dolor amet", views: 65, user_id: 456 },
    ],
    users: [
        { id: 123, name: "John Doe" },
        { id: 456, name: "Jane Doe" }
    ],
    comments: [
        { id: 987, post_id: 1, body: "Consectetur adipiscing elit", date: new Date('2017-07-03') },
        { id: 995, post_id: 1, body: "Nam molestie pellentesque dui", date: new Date('2017-08-17') }
    ]
}
```

```sh
Aarons-iMac:vue-gql-composition aaronksaunders$ json-graphql-server db.js
GraphQL server running with your data at http://localhost:3000/
```
You can now point your browser at the server and get the GraphiQL interface to check your data.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/63lm2rqx4dwz1ao9u1z8.png)

###Getting The Setup For The VueJS App
>[See Documentation for apollo-composable](https://v4.apollo.vuejs.org/guide-composable)

After setting up your base project using vue-cli we need to add the required packages for `apollo-composable` and graphql.

They are on separate lines for documentation purposes only...

```sh
npm install @vue/apollo-composable
npm install @vue/composition-api
npm install apollo-boost
npm install graphql
npm install vue-apollo
```
Next open `main.js` to star to add the client information for the graphql support

Add the imports to for the API integration and creating the Apollo client
```javascript
// GRAPHQL STUFF
import VueCompositionApi, { provide } from '@vue/composition-api'
import { DefaultApolloClient } from '@vue/apollo-composable'
import ApolloClient from 'apollo-boost'
```
Next lets create the apollo client, the url is from the output when we launched the `json-graphql-server`.
```javascript
// client apollo client
const apolloClient = new ApolloClient({
  connectToDevTools: true,
    uri: "http://localhost:3000"
})
```
And then finally we need to add the `VueCompositionApi` plugin since we are still not running vue3

Now we us the provide function from the composition api to make the apollo functionality available to the other components in the application.
```javascript
new Vue({
  // add the client to vue object
  setup () {
    provide(DefaultApolloClient, apolloClient)
  },
  render: h => h(App),
}).$mount('#app')
```

###Starting with Query - Get All Posts
We are not doing a deep dive into GraphQL so I will just briefly explain the query and the expected output.

- [Introduction to GraphQL](https://graphql.org/learn/)

This query will return the list of all of the posts and include the id of the associated user.
```javascript
// QUERY
const ALL_POST_QUERY = gql`
  {
    allPosts {
      id
      title
      user_id
    }
  }
`;
```
The query response object will look similar to this, so when accessing the data in the application it will be `data.allPost[]`
```javascript
{
  "data": {
    "allPosts": [
      {
        "id": "1",
        "title": "Lorem Ipsum",
        "user_id": "123"
      },
      {
        "id": "2",
        "title": "Sic Dolor amet",
        "user_id": "456"
      },
      {
        "id": "10",
        "title": "test",
        "user_id": "10"
      },
    ]
  }
}
```
Now that we have the query set lets get to the component setup.

In the `HelloWorld.vue` Component, we need to add our query and scaffold out the script section to support the new composition api.

First add the imports, and the query as a constant.
```javascript
<script>
import { gql } from "apollo-boost";
import { useQuery } from "@vue/apollo-composable";

// QUERY
const ALL_POST_QUERY = gql`
  {
    allPosts {
      id
      title
    }
  }
`;
```
Next we will add the `setup` section and include the `useQuery` function, passing it in the query we want to run.

You can see that the `useQuery` composible returns the following
- `result` - data response from the query
- `loading` - true | false indicating the loading state of the query, can be used to provide a visual status of the query
- `error` - error information if appropriate
```javascript
export default {
  name: "HelloWorld",
  setup() {
    // QUERY
    const { result, loading, error } = useQuery(
      ALL_POST_QUERY
    );

    return {
      result,
      loading,
      error
    };
  },
  methods: { }
};
</script>
```
If you run the application now and look in the vue-dev-tools, you will see the properties returned from the `setup` function bound to the component as data properties.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/xtbd3skk9aoug0tzpfxn.png)
Quickly put together some UI to show the query results. We are utilizing the `loading` property returned from `useQuery` to determined if we should display a loading messages and the using the `result.allPosts` to render the objects when the query is completed and finally if there is an `error` we show the error message.
```vuejs
<template>
  <div>
    <button @click="addPost">ADD POST</button>
    <div v-if="loading">
      <h2>Loading</h2>
    </div>
     <div v-else-if="error">
      <h2>{{error}}</h2>
    </div>
    <div v-else>
      <h2>Query Results</h2>
      <div v-for="p in result.allPosts" :key="p.id">{{p}}</div>
    </div>
  </div>
</template>
```
###Now A Mutation - Adding A Post
This mutation will add a post to the dataset. The way it is constructed require query parameters formatted as follows:
```json
{ title: "New Post Title", id : 100, userId : 10 }
```
```javascript
// MUTATION
const ADD_POST_MUTATION = gql`
  mutation createPost($title: String!, $id: ID!, $userId: ID!) {
    createPost(title: $title, views: 0, user_id: $userId, id: $id) {
      id
      title
    }
  }
`;
```
Next we will include in the existing `setup` section the `useMutation` function, passing it in the mutation we want to run.

We are structure this such that we will have access to a function `createPost` exposed for us to call to execute the query that will be bound to the component.

Note that because we already are returning `loading` & `error` from `useQuery` that we will need to structure the objects that we return a little differently. 
```javascript
// QUERY
const { result, loading, error } = useQuery(
  ALL_POST_QUERY
);

// MUTATION <== NEW
const {
  loading: mLoading,
  error: mError,
  mutate: createPost
} = useMutation(ADD_POST_MUTATION);

return {
  result,
  loading: loading || mLoading, <== NEW
  error: error || mError,       <== NEW
  createPost                    <== NEW
};
//
```
In the template section of the component we will and an input field and a button for the user to enter the `title` and the execute the `createPost` method associated with the `useMutation` composable.
```javascript
<template>
  <div>
    <input type="text" v-model="title" placeholder="enter the title" />
    <button @click="addPost">ADD POST</button>

...

  </div>
</template>
```
###Updating the Cache
After the item is added to the list, you will notice that it is not showing up in the list. The client will "update" items if they exist already but will not add new items to cache automatically... you need to do that.

there is an `update` option on `useQuery` that we can use to update the local apollo cache which will then update the UI.

when the update function is called the data we get is shaped as the response we defined in the mutation
```json
data: {
  createPost: {
    id: "1586711727281"
    title: "adssad"
    views: 0
    user_id: "200"
    __typename: "Post"
  }
}
```
we then use that data to update the apollo cache using the following code.
```javascript
// MUTATION
const {
  loading: mLoading,
  error: mError,
  mutate: createPost
} = useMutation(ADD_POST_MUTATION, {
  update: (cache, { data: { createPost } }) => {
    // get the posts from the cache...
    const data = cache.readQuery({ query: ALL_POST_QUERY });
    // add the new post to the cache
    data.allPosts.push(createPost);
    // write results back to cache
    cache.writeQuery({ query: ALL_POST_QUERY, data });
  }
});
```

{% youtube MNxgQ4Ba7S8 %}
###Conclusion
That's it for this post, in the next part I will add update and delete, and then clean up the UI a bit to make it more presentable.


**json-graphql-server:** https://github.com/marmelab/json-graphql-server
**@vue/apollo-composable:** https://v4.apollo.vuejs.org/guide-composable