GraphQLの旅(7) Reactで最小GraphQLフロントエンド(付録でSkaffold)

# react-apolloを使う

GraphQLのAPIを使用しデータを取得するフロントエンドアプリを作ります。
使用できるフレームワークは、ReactやVue.jsなどがあります。
今回はReact.jsを利用します。（前回は[Vue](https://qiita.com/Hiroyuki_OSAKI/items/2e0db565cfd5686eadf1)でした）

React.jsに加えて、apollo-client（GraphQLクライアントライブラリ）、そしてreactからapolloを使いやすくするreact-apolloを使います。

- [react-apollo](https://github.com/apollographql/react-apollo)

react-apolloは比較的ドキュメントが多いです。

# 前提

とあるGraphQLサーバにて`User`のAPIがあるとします。

```graphql
type User {
  id: ID! @unique
  name: String!
}
```

# create-react-appがインストールされたサーバでまずはひな型を作る

下記コマンドでひな型を作ります。

```sh
create-react-app <app_name>
```

# react-apolloなどライブラリを追加

```sh
yarn add apollo-boost react-apollo graphql-tag graphql
```

- `src/App.js`にGraphQLサーバへの接続を書く

**注：GraphQLサーバアドレスを書き換える**

```react
import { ApolloProvider } from "react-apollo";
import gql from "graphql-tag";
import ApolloClient from 'apollo-boost';
import { Query } from "react-apollo";

const client = new ApolloClient({
  uri: "http://<GraphQLサーバアドレス>"
});

const Users = () => (
  <Query
    query={gql`
      {
        users {
          id
          name
        }
      }
    `}
  >
    {({ loading, error, data }) => {
      if (loading) return <p>Loading...</p>;
      if (error) return <p>Error :(</p>;

      return data.users.map(({ id, name }) => (
        <div key={id}>
          <p>{`${id}: ${name}`}</p>
        </div>
      ));
    }}
  </Query>
);
```

- 最後に`<ApolloProvider></ApolloProvider>`の間に先ほどの`User`を挿入します。

```react
class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
        <ApolloProvider client={client}>
        <div>
          <h2>My first Apollo app</h2>
        </div>
        <Users/>
        </ApolloProvider>
      </div>
    );
  }
}
```

ファイル構成はこうなります。★を更新しました。

```sh
.
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
├── README.md
├── src
│   ├── App.css
│   ├── App.js　★
│   ├── App.test.js
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   └── registerServiceWorker.js
└── yarn.lock
```

# 起動

```sh
yarn start
```

これで、`http://localhost:3000/`にアクセスするとReactアプリが起動します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/96277/8c00504c-5dab-be21-df5e-1396d5b477ad.png)

注意：ここで"tokyo"などとデータが出てくるためには、[GraphQLサーバをあらかじめ用意しておく(prisma, graphql-yogaの場合)](https://qiita.com/Hiroyuki_OSAKI/items/cabc086cac06787be18e)必要があります。

# Appendix. SkaffoldによるKubernetes自動デプロイ

この後は余興。

- `skaffold.yaml`を追加

```yaml

apiVersion: skaffold/v1alpha2
kind: Config
build:
  artifacts:
  - imageName: react-apollo-sample
deploy:
  kubectl:
    manifests:
      - k8s/*
```

- skaffoldがKubernetes上にコンテナを起動するための設定用`k8s`フォルダを作成。下記を追加。

`k8s/pod.yaml`

```yaml

apiVersion: v1
kind: Pod
metadata:
  name: react-apollo-sample
  labels:
    app: react-apollo-sample
spec:
  containers:
  - name: react-apollo-sample
    image: react-apollo-sample
    ports:
    - containerPort: 3000
```

`k8s/service.yaml`

```yaml

kind: Service
apiVersion: v1
metadata:
  name: react-apollo-sample
spec:
  selector:
    app: react-apollo-sample
  ports:
  - protocol: TCP
    port: 80
    targetPort: 3000
    nodePort: 30080
  type: NodePort
```

- 開発用の環境をデプロイ（ファイル変更検知→自動再デプロイ）

```sh
skaffold dev
```

- 本番用の環境をデプロイ

```sh
skaffold run
```

さてさて、ようやっとこのあとはApollo Server。2.0もリリースされ、batchingなど多彩な機能が満載です。
複数のGraphQLサーバの連携を可能にするSchema stitchingに踏み込んでいきます。