Next.js+GrapqhQLでShopifyアプリを開発する

# はじめに
最近話題のShopifyでアプリを開発をしています。
はじめてGrapqhQLに触れ、Shopifyアプリ開発との親和性の高さ、拡張性の高さに驚きました。
GraphQLで開発するにあたって詰まった部分が多くあり解決策を残しておきます。

# この記事のターゲット
- Shopifyでアプリを開発始めたい人
- GraphQLはなんとなくわかる

# GraphQL+Next.jsのボイラープレートからプロジェクトを作成し動かす
[Shopify App CLI](https://github.com/Shopify/shopify-app-cli) を使って出力しましょう

```
shopify create node
```
対話式にいろいろ聞かれるので、適宜入力します。
完了し以下を実行するとインストールするためのURLが出力され、ストアへのアプリインストールができます。

```
shopify serve
```

インストール実行後、以下のような画面になりNext.jsが動いていることがわかります。

![Shopify.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52617/ef025bb5-c551-cc24-3d57-c68c43e2f63b.png)


ソースコードは以下のようになっているはずです。

https://github.com/hal256/shopify_graphql_app_example/tree/5709e5718213e1c79055754064a5e6a48b02ae47


# GrapqhQLクライアントをインストールする
デフォルトではGraphQLを動かすためのクライアントは入っていないのでインストールします。

```
yarn add @apollo/react-hooks
```

# Componentを作成する
## ShowProducts
ルートディレクトリにComponentsディレクトリを作成し、ShowProducts.jsを作成します。
その前にストアの管理画面左メニューの商品管理からテスト用で商品を一つ作成しておきましょう。


ソースコードはこちらです。

``` javascript
import React from "react";
import { useQuery } from "@apollo/react-hooks";
import { gql } from "apollo-boost";
const GET_PRODUCTS = gql`
  query GET_PRODUCTS {
    products(first: 10) {
      edges {
        node {
          id
          title
        }
      }
    }
  }
`;
import ApolloClient from "apollo-boost";
const client = new ApolloClient({
  fetch: fetch,
  fetchOptions: {
    credentials: "include",
  },
});
const ShowProducts = () => {
  const { data, loading, refetch } = useQuery(GET_PRODUCTS, { client: client });
  if (loading || !data.products) {
    return <div>Loading...</div>;
  }
  const products = data.products.edges.map((productEdge) => (
    <div key={productEdge.node.id}>
      <p>id: {productEdge.node.id}</p>
      <p>title:{productEdge.node.title}</p>
    </div>
  ));
  return (
    <div>
      {products}
      <button
        onClick={() => {
          refetch();
        }}
      >
        refetch
      </button>
    </div>
  );
};
export default ShowProducts;


```

この部分でShopifyに投げるGraphQLを定義します。

```
const GET_PRODUCTS = gql`
  query GET_PRODUCTS {
    products(first: 10) {
      edges {
        node {
          id
          title
        }
      }
    }
  }
`;

```

↑で定義したGraphQLは以下useQueryhookで実行され、dataに結果が入ります。

``` javascript

const { data, loading, refetch } = useQuery(GET_PRODUCTS, { client: client });
```

これで先程作成した商品が表示されているかと思います。

## AddProduct
次に、GraphQLでアプリから商品を作成してみましょう。


ComponentディレクトリにAddProduct.jsを作成します
ソースコードは以下です。

``` javascript
import React, { useState } from "react";
import { gql } from "apollo-boost";
import ApolloClient from "apollo-boost";
import { useMutation } from "@apollo/client";
const client = new ApolloClient({
  fetch: fetch,
  fetchOptions: {
    credentials: "include",
  },
});
const ADD_PRODUCT = gql`
  mutation ADD_PRODUCT($title: String!) {
    productCreate(input: { title: $title }) {
      product {
        id
      }
    }
  }
`;
const AddProduct = () => {
  const [addProduct] = useMutation(ADD_PRODUCT, { client });
  const [productTitle, setProductTitle] = useState("");
  return (
    <div>
      <label>
        Title
        <input
          type="text"
          value={productTitle}
          onChange={(event) => {
            setProductTitle(event.target.value);
          }}
        />
        <button
          onClick={() => {
            addProduct({
              variables: {
                title: productTitle,
              },
            });
          }}
        >
          Submit
        </button>
      </label>
    </div>
  );
};
export default AddProduct;

```

以下で保存するためのGraphQLを定義します。

```

const ADD_PRODUCT = gql`
  mutation ADD_PRODUCT($title: String!) {
    productCreate(input: { title: $title }) {
      product {
        id
      }
    }
  }
`;
```

ボタンをクリックすることで商品を追加できることが確認できると思います。

## まとめ

これで取得と追加一通りの処理の流れが確認できたと思います。
GraphQLからTypeScriptの型を生成することもでき、RestAPIより堅牢に書くためのコストが下がるのが良いと感じました。
ここから一歩進んで自分で作成したGraphQLサーバーと、ShopifyのGraphQLの結合も可能で、実際作ってみたところ機能拡張がかなり容易にできたのでこれもいつか記事にしたいと思います。