14
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Vue.js #2Advent Calendar 2018

Day 12

vuexなし縛り。vueとapollo-link-stateでカウンター作成

Last updated at Posted at 2018-12-10

こんな感じになります

ima ge.png

追記2018/12/13
Nuxt.js版ライブデモ on Netlifyを稼働。

ポイント

  • vuexは使わない
  • 代わり、apollo-link-stateと、vueからapolloを使いやすくするvue-apolloを使う
  • withClientStateを使ってLinkを作る
    • defaultsにフィールドcountSample、最初の値0を入れる
    • resolversにカウンタの値を増加させるmutationを作る
  • コンポーネントからは$のついていないapolloというフィールドで、どの変数に値を入れるかを設定する
    • mutationthis.$apollo.mutateで呼び出す

Linkを作る

  • stateLinkという、普通のGraphQLのlinkとは違うLinkを作成します
main.ts
import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import VueApollo from 'vue-apollo'
import { withClientState } from 'apollo-link-state';
import { readCache, writeCache } from './apollo-link-state-store'

Vue.use(VueApollo)

const stateLink = withClientState({
  cache: new InMemoryCache(),
  defaults: {
    countSample: 0
  },
  resolvers: {
    Mutation: {
      increment: (obj: any, args: any, {cache}: any) => {
        var rtn = readCache(cache, "countSample")
        writeCache(cache, "countSample", rtn + 1)
        return null
      },
    },
  },
});

const apolloProvider = new VueApollo({
  defaultClient: new ApolloClient({
    link: stateLink,
    cache: new InMemoryCache(),
    connectToDevTools: true

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

こうして関数化しておくと楽(GraphQLお作法の隠蔽)

  • apollo-link-stateは癖が強いので、自分で簡単関数apollo-link-state-storeを作りました。
apollo-link-state-store.ts
import gql from 'graphql-tag'

const argRead = (key: string) => gql`{ ${key} @client}`

const argReadCache = (key: string) => {
    return { query: argRead(key)}
}

const argWriteCache = (key:string, value: any) => {
    return {data: { [key]: value }}
}

//これをmain.tsから呼ぶ
export const readCache = (cache: any, key:string) => {
    return cache.readQuery(argReadCache(key))[key]
}

//これをmain.tsから呼ぶ
export const writeCache = (cache: any, key: string, value: any) => {
    return cache.writeData(argWriteCache(key, value))
}

//これをコンポーネントから呼ぶ
export const argMutate = (mutation: string) => {
    return {
        mutation: gql`mutation { ${mutation} @client }`
    }
}

//これをコンポーネントから呼ぶ
export const apolloState = (key: string) => {
    return {
        query: argRead(key),
        loadingKey: 'loading'
    }
}

そしてコンポーネントからはこう呼ぶ

<template>
  <div>
    <div> {{ countSample }} </div>
    <v-btn color="success" v-on:click="increment()" > +1 </v-btn>
  </div>
</template>

<script>
import { apolloState, argMutate } from '../apollo-link-state-store'

  export default {
    apollo: {
      countSample: apolloState("countSample")
    },
    data () {
      return {
        countSample: 0
      }
    },
    methods: {
      increment() {
        this.$apollo.mutate(argMutate("increment"))
      }
    },

  }
</script>

まとめ

  • 癖が強いapollo-link-stateの作法を、半分くらい関数化して隠蔽するapollo-link-state-store.tsを作った。
  • Vuexなくてもストアは作れる
  • ただ、それが本当に嬉しいのかは人によるかな
  • apollo-link-stateを使うことで、reduxやvuexに縛られない、フレームワークをまたぐようなストアもできそうな気がする。そういうのってマイクロフロントエンドとして必要にならないだろうか。FiNCなどの先人を切っている方がそういうストアをどうしているのかが気になる。

おまけ

この記事こちらこちらを参照しながら、

  • Nuxt.jsで簡単なサンプルプログラム作成
  • 今回のapollo-link-stateカウンターを移植

ができました。
ソースコードはこちら。

そしてNetlify上のライブデモです。

ご査収ください

14
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?