Skip to content

Latest commit

 

History

History
259 lines (189 loc) · 9.3 KB

01_what_gql.md

File metadata and controls

259 lines (189 loc) · 9.3 KB

Chapter 1. はじめての GraphQL

ToC

はじめに

このワークショップの目的は参加者に React を使った GraphQL のフロントエンド開発を学んでもらうことです。

いきなりフロントエンドのコードを書く前に、まずは「GraphQL とはどういうものなのか」「どのようなことができるのか」の概要を知ってもらった方が良いと考え、この章を用意しました。GraphQL の概要をご存知の方は読み飛ばして構いません。

GraphQL は Facebook が 2012 年頃から開発を始めたクエリ言語です。2015 年にオープンソース化され、2018 年からは GraphQL Foundation という独立した組織でメンテナンスされるようになっています。

一貫した型システムやそれに付随する静的検証が言語仕様に組み込まれており、 JavaScript や Ruby, Java など様々なプログラミング言語で汎用的に API 通信が行えるように設計されています。

触ってみよう

能書きはこれくらいにしておき、実際に GraphQL でクエリを実行しながら見ていきましょう。

まずは GraphQL server を立ち上げてみましょう。本ワークショップでは実装済みの GraphQL Server を使います。

$ cd server
$ npm i
$ npm run seed
$ npm start

上記のコマンドが正常に実行されると、以下のアドレスにアクセスできるようになります:

http://localhost:4010/graphql

この画面は GraphQL プレイグラウンドと呼ばれます。

はじめての Query

プレイグラウンドの左側はエディタになっています。このエディタ部分に以下のように書いてみて、実行ボタンをクリックしてください。

query {
  products {
    id
    name
  }
}

商品のリストが data として取得できましたか?

取得するフィールドを追加する

query {
  products {
    id
    name
    imageURL # <--- 追加
  }
}

ネストしたオブジェクトの取得

query {
  products {
    name
    reviews
  }
}

これはエラーになってしまいます。

以下の様に、 reviews に続けて { } を記述し、その中にフィールド名を書いてから実行してみましょう。

query {
  products {
    name
    reviews {
      # オブジェクトについては、下層のフィールド名をきちんと列挙する必要がある
      id
      commentBody
    }
  }
}

Query と型

GraphQL は「どのような検索ができるか」「どのような更新をおこなえるか」について、静的な型と一緒に運用されます。

プレイグラウンドの右側から「Schema」をクリックしてみましょう。

この Server で提供されている GraphQL サービスのスキーマを観ることができます。

type Query {
  products: [Product]!
  product(id: ID!): Product
}
# 商品。だがし。
type Product {
  id: ID!
  name: String!
  imageURL: String!
  description: String!
  price: Int!
  reviews: [Review!]!
}

# 商品のレビュー
type Review {
  id: ID!
  star: Int!
  commentBody: String!
}

ProductReview など type というキーワードからはじまっている部分はタイプと呼ばれます(正確には "Output Type" だが、通常は「タイプ」と呼ばれることが多い)。type はフィールド名とそのフィールドの値の型で定義されるオブジェクトライクな構造を示しています。

先程ネストの例で見たように、フィールドの type がまた別の type を指すこともありますし、自己参照や循環参照することも許容されています。Query という名前の type は特殊な意味をもっており「このスキーマで実行可能なトップレベルのクエリ」を意味しています。

IDString は基本型(GraphQL の用語では Scalar 型という)に分類されます。

名前 説明
Boolean 真偽値
Int 整数値
Float 浮動小数点の数値型
String 文字列型
ID 一意識別子として利用される値の型

ID! のように、型名の後ろに ! をつけると「そのフィールドは絶対に値がある」という意味になります。逆に ! が無い場合は「値が取得できない可能性がある」という意味になります。

[String] のように、型名を [ ] で囲むと「囲んだ型を値に持つリスト」という意味になります。 [[String]] のように二次元リストのようにすることも可能です。

これ以外にも InterfaceUnion , Enum などの概念も存在しますが、ここでは割愛します。

引数付きの Query

先程みたように、このサービスでは product という Query も提供されていることがスキーマから分かりました。今度はこれを実行してみましょう。

type Query {
  product(id: ID!): Product
}
query {
  product(id: "002") {
    name
  }
}

product(id: ID!): Product にあるとおり、 Product の型名末尾には ! が付いていないことからも「このクエリは null を返すこともある」ということがわかりますね。

存在しない商品 id(e.g. "005") に変更すると null となるパターンも確認できます。

引数を変数化する

実際のアプリケーションでは、クエリ中の商品 id を動的に変更したくなります。例えばアプリケーションの画面 URL /products/:id から Router Library を使って URL パスパラメータを取り出すようなケースです。

GraphQL には、静的な Query に対して変数を埋め込む機構が用意されています。

query ProductQuery($id: ID!) {
  product(id: $id) {
    name
  }
}

SQL の Prepared Statement と似ていますね。

変数を使う場合、 query ProductQuery のように、Query に名前をつける必要があります。関数名のようなものです。また変数名は "$" から始まっている必要があります。

Query の変数は JSON として用意します。プレイグラウンドの「Query Variables」をクリックして以下の JSON を記述しましょう。

{
  "id": "002"
}

動的に Query を組み立ててはいけない

詳細は割愛しますが、以下のように Template String などで動的に GraphQL の Query を組み立てるのは絶対にやめてください

const productId = router.query.params.productId;

const query = `
  query {
    product(id: "${productId}") {
      name
    }
  }
`;

余裕があれば、どのような不都合が生じるか考えてみてください。

Mutation でサーバーのデータを変更する

ここまでは Query を扱ってきました。

続いて、Server 上の値の変更を扱ってみましょう。

GraphQL では破壊的な操作はすべて Mutation と呼ばれる操作で実行する必要があります。

  • Query: 安全な処理. REST では GET
  • Mutation: 安全でない、すなわち破壊的な処理. REST での POST/PUT/DELETE/PATCH

文法は Query の場合と同様です。

今回のスキーマには以下で定義された Mutation がありますので、これを実行してみましょう。

type Mutation {
  # 指定した商品にレビューを追加する
  addReview(productId: ID!, addReviewInput: AddReviewInput!): Review
}
mutation AddReview {
  addReview(
    productId: "002"
    addReviewInput: { commentBody: "すっぱい", star: 1 }
  ) {
    id
    commentBody
    star
  }
}

Mutation 実行後にもう一度 ProductQuery を実行し、レビューが投稿できたことを確かめてみましょう。


Chapter 2 へ