Next.jsとHasuraを連携してデータを画面に出すところまでやる（ためのpages/配下のコンポーネント作成）...4

## はじめに

以下のゴールを達成するため、本日はついに、Next.jsとHasuraを連携してデータを画面に出すところまでやります。

特に今回は、Next.jsでApollo Clientを使ってSSR(SSG)する仕組みの部分を見て行くと思います。

![イメージ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/a82854a4-b7ba-4ddd-bf48-c7678f452d7f.jpeg)

Hasuraにあるデータやエンドポイントは既に用意してあります。

## 最終的なゴール

以下のような構成のアプリを作ることです。

![スクリーンショット 2021-10-18 17.27.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/e8a9a2e1-2723-4fec-77ef-be3b9eefdd81.png)

### 目的

- 仕事で使っている技術のキャッチアップと復習
- 使う可能性がある技術の理解度向上

## 前回のおさらい

Next.jsとHasuraを連携してデータを画面に出すために、

apolloClientインスタンスを作成したり、初期化に関する処理を作成しました。

詳細👇

https://qiita.com/ryosuketter/items/a626062a59bcf67b3151

次に、pages配下にuseQueryを書きました。

詳細👇

https://qiita.com/ryosuketter/items/904d4d0d1a37bfc5b69c

## pages配下のコンポーネント実装

前回はここまで書いたと思います。

```ts
import { VFC } from 'react'
import Link from 'next/link'
import { useQuery } from '@apollo/client'
import { GET_USERS } from '../queries/queries'
import { GetUsersQuery } from '../types/generated/graphql'
import { Layout } from '../components/Layout'

const FetchMain: VFC = () => {
  const { data, error } = useQuery<GetUsersQuery>(GET_USERS)
  return()
}
export default FetchMain
```

通信して、エラーだった場合、そうでない場合でコンポーネントを作成しましょう。

```ts
import { VFC } from 'react'
import Link from 'next/link'
import { useQuery } from '@apollo/client'
import { GET_USERS } from '../queries/queries'
import { GetUsersQuery } from '../types/generated/graphql'
import { Layout } from '../components/Layout'

const FetchMain: VFC = () => {
  const { data, error } = useQuery<GetUsersQuery>(GET_USERS)
  if (error)
    return (
      <Layout title="Hasura fetchPolicy">
        <p>Error: {error.message}</p>
      </Layout>
    )
  return (
    <Layout title="Hasura fetchPolicy">
      <p className="mb-6 font-bold">Hasura main page</p>
      {data?.users.map((user) => {
        return (
          <p className="my-1" key={user.id}>
            {user.name}
          </p>
        )
      })}
      <Link href="/hasura-sub">
        <a className="mt-6">Next</a>
      </Link>
    </Layout>
  )
}
export default FetchMain
```

通信ステータスごとに、returnされるコンポネントはどちらも`<Layout/>`に囲みます。

```ts
{data?.users.map((user) => {
  return (
    <p className="my-1" key={user.id}>
      {user.name}
    </p>
  )
})}
```

この解説を少しします。

`data?.users`は、オプショナルチェーンが書かれています。

`data`が`null | undefined`だと、`data.users`これ、エラーになります

ですが、オプショナルチェーンで書くとそうならず、関数`useQuery`の結果`data`が存在しない場合は最終的に何も返らないコンポネントになります。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining

関数`useQuery`の結果`data`が存在する場合は配列の要素をそれぞれ、コンポネント（pタグ）作成しています。

実際にブラウザ（ローカル環境）を見ると

```
http://localhost:3000/hasura-main
```

![スクリーンショット 2021-11-03 18.26.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/70e9bf15-9e2f-48d4-73a6-166631d3400f.png)

HasuraのGraphQlサーバからUsersデータを取得できたことを確認できました。

![スクリーンショット 2021-11-03 18.29.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/f9ad898e-4f31-e9a7-132b-a4d5af19bb55.png)

:v_tone1:

コンソールでdataを確認するとこんな感じ

```json
{
   "users":[
      {
         "__typename":"users",
         "id":"5f172cd2-221c-4ea5-8b83-6420b18860ab",
         "name":"lilly"
      },
      {
         "__typename":"users",
         "id":"0458dd7d-70a5-4087-88c7-d8c3ed51a505",
         "name":"bob"
      },
      {
         "__typename":"users",
         "id":"f6a27de5-2f26-4e14-8435-bc463aabe791",
         "name":"john"
      }
   ]
}
```

GraphQlでは、キャッシュのデータが自動的に正規化され、`"__typename":"users"`というKey & Valueが自動生成されます。

apolloクライアントが、保存されたキャッシュを追跡する場合、この場合は、`id`と`__typename`を組み合わせたものをKeyとして探索します。

今日のところは以上です。

次の記事では、Hasuraから取ったデータをキャッシュして、そのキャッシュデータを他のコンポーネントが再度が利用するための方法を書いていきます。

![スクリーンショット 2021-11-03 21.21.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/7da9815a-ff5c-8dd5-0e82-b78b6cfe7ed2.png)

## アウトプット100本ノック実施中

https://qiita.com/ryosuketter/items/713474dbd009870e4103