はじめに
Next.js の SG + ISR (with Apollo) の仕組みを作りながら学んでみたシリーズ
このシリーズでは、Hasuraで用意した仮想のユーザーデータを外部APIとして取得しながら、
ユーザーの一覧ページと詳細ページを作りながら、SGと ISRを学ぶ記事です。
今回は、ユーザーの一覧ページのコンポーネント作成の実装について書きます。
目次
- 実装
- 一覧ページ
- getStaticProps
- 必要なモジュールのimport 👈 今回はコレ
- interface作成 👈 今回はコレ
- コンポーネント作成 👈 今回はコレ
- 詳細ページ
- 一覧ページ
- 検証
SGという用語に関して
SSGと言ったり、SGと言ったりするかもしれませんが、SSGはかつての呼び方なのでSG(Static Generate)に統一して書こうと思います。
仕組みは同じものだと思ってください。
最終的なゴール
以下のような構成のアプリを作ることです。
目的
- 仕事で使っている技術のキャッチアップと復習
- 使う可能性がある技術の理解度向上
必要なモジュールのimport
import { VFC } from 'react'
import Link from 'next/link' // 詳細ページへリンクするので
import { GetStaticProps } from 'next' // 関数getStaticPropsの型
import { initializeApollo } from '../lib/apolloClient' // Hasuraにデータ取得するためのGraphQlクライアントメソッド
import { GET_USERS } from '../queries/queries' // Hasuraにデータ取得するためのクエリ
import { GetUsersQuery, Users } from '../types/generated/graphql' // クエリを書いたら自動生成される型情報
import { Layout } from '../components/Layout'
interface作成
前回実装した関数getStaticProps
からreturnされる users
ここね👇
return {
props: { users: data.users },
revalidate: 1,
}
このusers
は今回実装するコンポーネントのpropsに渡ってきます。
そのpropsの型をinterfaceで定義します。
interface Props {
users: ({
__typename?: 'users'
} & Pick<Users, 'id' | 'name'>)[]
}
配列で定義されています。その中身はオブジェクトになっていて、typesがusers
、id``name
が定義されます。
Usersをホバーすると全体感把握できますが、その中から必要なものをPick UP してid
とname
って感じです。
実際に以下の記事(Hasura)で作成してきたユーザーデータを
関数getStaticProps
経由で取得した結果を
console.log(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": "Paul"
}
]
interface通りですね。
コンポーネント作成
const HasuraSG: VFC<Props> = ({ users }) => {
console.log(users)
return (
<Layout title="Hasura SG">
<p className="mb-3 font-bold">SG+ISR</p>
{users?.map((user) => {
return (
<Link key={user.id} href={`/users/${user.id}`}>
<a className="my-1 cursor-pointer" data-testid={`link-${user.id}`}>
{user.name}
</a>
</Link>
)
})}
</Layout>
)
}
export default HasuraSG
users
が存在すれば、ユーザーの数分だけ詳細ページへのリンクを作成しています。
ブラウザ確認するとSGで取得されたページが表示されます。
ためしにブラウザのJSを無効化してもリロードしても表示されます。
なぜなら、前回説明したpre-rendering
(意味を先に言うと、事前にHTMLを生成すること)が、適切に機能しているからです。
Reactだけで作った場合、こうはなりません。
作成したファイル
長いので折り畳みました。
import { VFC } from 'react'
import Link from 'next/link'
import { GetStaticProps } from 'next'
import { initializeApollo } from '../lib/apolloClient'
import { GET_USERS } from '../queries/queries'
import { GetUsersQuery, Users } from '../types/generated/graphql'
import { Layout } from '../components/Layout'
interface Props {
users: ({
__typename?: 'users'
} & Pick<Users, 'id' | 'name'>)[]
}
const HasuraSG: VFC<Props> = ({ users }) => {
console.log(users)
return (
<Layout title="Hasura SG">
<p className="mb-3 font-bold">SG+ISR</p>
{users?.map((user) => {
return (
<Link key={user.id} href={`/users/${user.id}`}>
<a className="my-1 cursor-pointer" data-testid={`link-${user.id}`}>
{user.name}
</a>
</Link>
)
})}
</Layout>
)
}
export default HasuraSG
export const getStaticProps: GetStaticProps = async () => {
const apolloClient = initializeApollo()
const { data } = await apolloClient.query<GetUsersQuery>({
query: GET_USERS,
})
return {
props: { users: data.users },
revalidate: 1,
}
}
まとめ
今回は、ユーザーの一覧ページのコンポーネント作成の実装について書きました。
次回
アウトプット100本ノック実施中