Next.js_2 (ApolloClientとmakeVar編)

typescriptのmicrosoft公式ドキュメント

https://www.typescriptlang.org/docs/handbook/2/basic-types.html

海外でのわかりやすいチートチャート

https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/forms_and_events

■7. 基本Layoutの作成

7-1. componentsディレクトリ直下に、Layout.tsxを作成

cd components
touch Layout.tsx(macのターミナル)
New-Item Layout.tsx(Windowsのシェルスクリプト)

Layout.tsx はじめの一歩。

ReactNode→childrenをPropsで渡すので、そのデータ型としてReactNodeを設定。

VFC→Reactのファンクショナルコンポーネント(VFC)のデータ型で、childrenのデータ型を明示的に含まない。

import { ReactNode, VFC } from 'react'
import Head from 'next/head'
import Link from 'next/link'
import Image from 'next/image'

interface→「型」を、アプリケーション全体を通して定義する。

https://docs.microsoft.com/ja-jp/learn/modules/typescript-implement-interfaces/1-introduction

Propsというデータ型で、childrenとtitleを、それぞれReactNode型、String型で型を作っておく。

interface Props {
  children: ReactNode
  title: string
}

typescriptを使ったコンポーネントの基本形。

ここで割り当てられているtitleのテキストは、デフォルトの値。

export const Layout: VFC<Props> = ({
  children,
  title = 'Welcome to Nextjs',
}) => {
  return (
    <div>

    </div>
  )
}

また、リンクの箇所には

<Link href="/">
    <a
      data-testid="home-nav"
      className="text-gray-300 hover:bg-gray-700 px-3 py-2 rounded"
    >
      Home
    </a>
  </Link>

として、このリンクが押されたかをテストで識別するために、aタグに「data-testid」で値を設定しておく。

全体は以下

import { ReactNode, VFC } from 'react'
import Head from 'next/head'
import Link from 'next/link'
import Image from 'next/image'

interface Props {
  children: ReactNode
  title: string
}

export const Layout: VFC<Props> = ({
  children,
  title = 'Welcome to Nextjs',
}) => {
  return (
    <div className="flex flex-col justify-center items-center min-h-screen text-gray-600 text-sm font-mono">
      <Head>
        <title>{title}</title>
      </Head>
      <header>
        <nav className="bg-gray-800 w-screen">
          <div className="flex items-center pl-8 h-14">
            <div className="flex space-x-4">
              <Link href="/">
                <a
                  data-testid="home-nav"
                  className="text-gray-300 hover:bg-gray-700 px-3 py-2 rounded"
                >
                  Home
                </a>
              </Link>
              <Link href="/local-state-a">
                <a
                  data-testid="makevar-nav"
                  className="text-gray-300 hover:bg-gray-700 px-3 py-2 rounded"
                >
                  makeVar
                </a>
              </Link>
              <Link href="/hasura-main">
                <a
                  data-testid="fetchpolicy-nav"
                  className="text-gray-300 hover:bg-gray-700 px-3 py-2 rounded"
                >
                  fetchPolicy(Hasura)
                </a>
              </Link>
              <Link href="/hasura-crud">
                <a
                  data-testid="crud-nav"
                  className="text-gray-300 hover:bg-gray-700 px-3 py-2 rounded"
                >
                  CRUD(Hasura)
                </a>
              </Link>
              <Link href="/hasura-ssg">
                <a
                  data-testid="ssg-nav"
                  className="text-gray-300 hover:bg-gray-700 px-3 py-2 rounded"
                >
                  SSG+ISR(Hasura)
                </a>
              </Link>
              <Link href="/hooks-memo">
                <a
                  data-testid="memo-nav"
                  className="text-gray-300 hover:bg-gray-700 px-3 py-2 rounded"
                >
                  custom hook + memo
                </a>
              </Link>
            </div>
          </div>
        </nav>
      </header>
      <main className="flex flex-1 flex-col justify-center items-center w-screen">
        {children}
      </main>
      <footer className="w-full h-12 flex justify-center items-center border-t">
        <a
          className="flex items-center"
          href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
          target="_blank"
          rel="noopener noreferrer"
        >
          Powered by{' '}
          {/* <img src="/vercel.svg" alt="Vercel Logo" className="h-4 ml-2" /> */}
          <Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
        </a>
      </footer>
    </div>
  )
}

次に、pages/index.tsxを編集

import { VFC } from 'react'
import { Layout } from '../components/Layout'

const Home: VFC = () => {
  return (
    <Layout title="Home">
      <p className="text-3xl font-bold">Next.js + GraphQL</p>
    </Layout>
  )
}

export default Home

として、このリンクが押されたかをテストで識別するために、aタグに「data-testid」で値を設定しておく。

styles/Home.module.cssは使わないので削除。

https://www.notion.so1ef419902ceee7b9400418311aa69504