NuxtでApolloを使わずにGraphQLを扱ってみる

# はじめに

Vue,NuxtでGraphQLでApolloを扱う場合、[vue-apollo](https://github.com/Akryum/vue-apollo)を使われることが多いかなと思います。
vue-apolloは非常に高機能なライブラリで、キャッシュを使えたりgqlでクエリを認識したりと非常に便利だと思いますが、一方で初めて使う方には敷居が高いようにも感じます。
特にキャッシュ周りを理解せずに使うと、 `なんでデータ更新したのに反映されないの？` みたいなことが起こると思います。

そこで、`NuxtでGraphQLを味見してみたい` くらいの温度間で使う場合にvue-apolloよりも敷居が低いものはないかなと調べてみると、[prisam/graphql-request](https://github.com/prisma/graphql-request)が良さそうかなと。

READMEにも、
![スクリーンショット 2018-12-14 10.25.23.png](https://qiita-image-store.s3.amazonaws.com/0/173370/e5925022-9f91-e5f7-26e1-117b6629f2d4.png)

こう書かれているのでまさにちょうど良い感じそうな気がしました。

ということで、今回は[prisam/graphql-request](https://github.com/prisma/graphql-request)を使ってGraphQLを扱う例を実装してみました。

# 成果物

今回実装したサンプルは[こちら](https://github.com/TsukasaGR/nuxt-graphql-request-example)に置いてあります。

# 前提

- nuxt: 2.3.4
- npxでinstallしたての状態を想定しています
　　　　<img width="662" alt="スクリーンショット 2018-12-14 10.38.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/173370/c4489983-4b04-990f-fa27-a24364fbaaea.png">
- graphqlサーバーは[こちら](https://qiita.com/TsukasaGR/items/1a8b0020e5e83e7a46c7)のリポジトリを使っています

## graphql-requestを導入する

npm/yarnでインストールするだけです。

```sh
yarn add graphql-request
```

## GrapｈQLを扱うサンプルページを追加する

```diff:layouts/default.vue
<template>
-<v-app dark>
+<v-app>
.
.
.
</template>
<script>
  export default {
    data() {
      return {
        clipped: false,
        drawer: true,
        fixed: false,
        items: [
          { icon: 'apps', title: 'Welcome', to: '/' },
          { icon: 'bubble_chart', title: 'Inspire', to: '/inspire' },
+         { icon: 'fiber_new', title: 'GraphQL', to: '/graphql' }
        ],
        miniVariant: false,
        right: true,
        rightDrawer: false,
        title: 'Vuetify.js'
      }
    }
  }
</script>
```

```vue:pages/graphql.vue
<template>
  <v-layout>
    <v-flex text-xs-center>
      <h1>GraphQLサンプルページ</h1>
    </v-flex>
  </v-layout>
</template>
```
こちらのページでGraphQLを扱います。
![スクリーンショット 2018-12-14 10.54.24.png](https://qiita-image-store.s3.amazonaws.com/0/173370/4aefe86f-29a0-7e0c-b58a-1f9401cf69e0.png)


# 使ってみる

## クエリを実行してみる

Usageを参考に実装してみます。
template, styleは割愛しますのでサンプルのリポジトリをご覧ください

```vue:pages/graphql.vue
<script>
import { request, GraphQLClient } from 'graphql-request'

export default {
  data() {
    return {
      client: 0,
      endPoint: 'http://127.0.0.1:8000/graphql',
      users: []
    }
  },
  created() {
    this.clientInitialize()
  },
  methods: {
    clientInitialize() {
      this.client = new GraphQLClient(this.endPoint, { headers: {} })
    },
    getUsers() {
      const query = `
        query users($count: Int!) {
          users(count: $count) {
            data {
              id
              name
              email
            }
          }
        }
      `
      const variables = { count: 10 }

      this.client.request(query, variables).then(data => (this.users = data.users.data))
    }
  }
}
</script>
```

これで`USERSを取得する`ボタンを押下するとデータが取得出来ました。
![スクリーンショット 2018-12-14 11.42.03.png](https://qiita-image-store.s3.amazonaws.com/0/173370/3d0fb807-153a-fed8-9f28-0b2f60648fbf.png)

## ミューテーションを実行してみる

ミューテーションも記述はクエリと変わらないので愚直に書いていきます。

```vue:pages/graphql.vue
<script>
import { GraphQLClient } from 'graphql-request'

export default {
  data() {
    return {
      client: 0,
      endPoint: 'http://127.0.0.1:8000/graphql',
      users: [],
      editId: null,
      editName: null,
      editEmail: null
    }
  },
  created() {
    this.clientInitialize()
  },
  methods: {
    clientInitialize() {
      this.client = new GraphQLClient(this.endPoint, { headers: {} })
    },
    getUsers() {
      const query = `
        query users($count: Int!) {
          users(count: $count) {
            data {
              id
              name
              email
            }
          }
        }
      `
      const variables = { count: 10 }

      this.client.request(query, variables).then(data => (this.users = data.users.data))
    },
    updateUser() {
      const query = `
        mutation updateUser(
          $id: ID
          $name: String
          $email: String
        ) {
          updateUser(
            id: $id
            name: $name
            email: $email
          ) {
            id
            name
            email
          }
        }
      `
      const variables = { id: this.editId, name: this.editName, email: this.editEmail }

      this.client.request(query, variables).then(data => {
        // dataのusersを更新してあげたほうが無駄な通信は発生しませんが、
        // 今回は味見目的なので更新後はまるっと読み込み直しています
        this.getUsers()
      })

      this.resetEditValues()
    },
    setEditValues(user) {
      this.editId = user.id
      this.editName = user.name
      this.editEmail = user.email
    },
    resetEditValues() {
      this.editId = null
      this.editName = null
      this.editEmail = null
    }
  }
}
</script>
```

データが更新出来ていることも確認出来ました。
![mutation.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/173370/24784740-56ce-96fa-468d-98d32f64daca.gif)

# さいごに

もう少し実用する例としてのところまでやりたかったのですがクエリとミューテーションだけで終ってしましました。。
この記事の内容であればREAME見れば十分じゃんという内容ですので、折を見て実際に利用する際のモジュール化のサンプルまでは追記しようと思います