LoginSignup
8
5

Next.jsの基本的な使い方(個人学習の備忘録)

Posted at

この記事はNext.jsの個人学習のアウトプットです。

Udemyの講座【2023年最新】React(v18)完全入門ガイド|Hooks、Next.js、Redux、TypeScript(CodeMafia)から引用・参照・コピーペーストしています。

1.Next.jsとは

  • React開発のためのフレームワーク
  • 高度なアプリケーションを作成するために、様々な機能を提供
    ┗ルーティングやサーバー側でのレンダリングなど
  • Vercelが提供している

Reactとの違い

  • React
    UIを構築するための機能を提供するライブラリ

  • Next.js
    react開発のための機能を提供するフレームワーク

Next.jsの主な機能

  • 複数のレンダリング方法(SSR、SG、ISG)
  • ファイルベースルーティング(ダイナミックルート)
  • APIの作成(API Routes)
  • デベロッパーに優しい開発環境(ゼロコンフィグ)

2.ルーティング

Next.jsは、pagesフォルダ内のファイル(またはディレクトリ)構成に対応してルーティングを行います。

src/pages/index.js
export default function Home() {
  return (
    <h1>Home</h1>
  )
}

// http://localhost:3000/

スクリーンショット 2023-06-24 15.49.32.png

ブラウザでlocalhost:3000にアクセスすると、作成したページが表示されます。

実行結果
スクリーンショット 2023-06-24 15.55.44.png

Next.jsはデフォルトエクスポートの関数がそのまま関数として表示されることになるので、例えば「blog-router」というフォルダを作成し、index.js内で同じように関数コンポーネントをデフォルトエクスポートすると「blog-router」というパスに対してページが表示されます。

src/pages/blog-router/index.js
export default function Blog() {
  return <h1>Blog Page</h1>
}

// http://localhost:3000/blog-router

スクリーンショット 2023-06-24 15.57.47.png

実行結果
スクリーンショット 2023-06-24 15.56.22.png

index.js以外のファイルで作成した場合は、パスはjavascriptのファイル名まで続けて指定する必要があります。

src/pages/blog-router/first.js
export default function First() {
  return <h1>Blog First Page</h1>
}

// http://localhost:3000/blog-router/first

スクリーンショット 2023-06-24 16.00.54.png

実行結果

スクリーンショット 2023-06-24 16.01.57.png

動的なルーティング

ダイナミックルーティングを用いると、URLの一部分を動的な値に変換することができるので、jsファイルのひとつだけ作成すればいいことになります。

123と数値が動的に変わっていくようなURLに対応するダイナミックルーティング

src/pages/blog-router/[number].js
export default function Number() {
  return <h1>[number] Page</h1>
}

// http://localhost:3000/blog-router/1
// http://localhost:3000/blog-router/2
// http://localhost:3000/blog-router/3

スクリーンショット 2023-06-24 16.11.31.png

実行結果
ezgif.com-video-to-gif (7).gif

フォルダにダイナミックルーティングを用いることも可能です。フォルダ名に[name]にすると、動的に変更することが可能になります。

src/pages/blog-router/[name]/setting.js
export default function Setting() {
  return <h1>[name] Setting</h1>
}

// http://localhost:3000/blog-router/a/setting
// http://localhost:3000/blog-router/b/setting
// http://localhost:3000/blog-router/c/setting

スクリーンショット 2023-06-24 16.34.36.png

実行結果
ezgif.com-video-to-gif (8).gif

注意

同階層に2つのダイナミックルーティングを作成することはできません。

スクリーンショット 2023-06-24 16.25.39.png

3.指定されたパスの値をjsで取得する

動的に変化するパスをjsで取得するにはどうすれば良いでしょうか。
2つの方法があります。

方法①getServerSidePropsという関数を使用する

propsというプロパティに設定された値が、この関数コンポーネントのpropsとして渡ってきます。

src/pages/blog-router/[name]/setting.js

// propsにhelloを渡す
export default function Setting({ hello }) {
  return <h1>{hello}</h1>
}

export async function getServerSideProps(){
  return { 
    props: { hello: "こんにちは" } 
  }
}

スクリーンショット 2023-06-24 17.15.37.png

実行結果
スクリーンショット 2023-06-24 17.13.11.png

queryを用いて、動的なパス部分を取得

今回の[name]の動的なパスに関しては、引数でcontextが渡ってきて、その中のqueryというオブジェクトの中に格納されています。
queryを渡してあげれば、画面上をどのようなパスで渡ってきたのか表示することができます。

src/pages/blog-router/[name]/setting.js
export default function Setting({ query }) {
  return <h1>{query.name}</h1>
}

export async function getServerSideProps({ query }){
  return { 
    props: { query } 
  }
}

スクリーンショット 2023-06-24 17.19.20.png

ezgif.com-video-to-gif (9).gif

方法② Next.jsが提供するRouterというライブラリからReactフックを読み込む

src/pages/blog-router/[name]/setting.js
import { useRouter } from "next/router";

export default function Setting({ query }) {
  const router = useRouter();
  return <h1>routerから取得:{router.query.name}</h1>;
}

export async function getServerSideProps({ query }) {
  return {
    props: { query },
  };
}

スクリーンショット 2023-06-24 17.31.11.png

ezgif.com-video-to-gif (10).gif

これら2つの方法で、動的なルートの部分を取得することができます。

4.useRouter を使って画面遷移を行う

buttonタグにclickイベントを定義し、routerのpushメソッドを使用します。この時スラッシュとすれば、rootのパスに一致することになるので、TOPページに戻ることになります。

src/pages/blog-router/[name]/setting.js
import { useRouter } from "next/router";

export default function Setting({ query }) {
  const router = useRouter();
  const clickHandler = () => {
    router.push('/')
  }
  return (
    <>
      <h1>routerから取得:{router.query.name}</h1>
      <button onClick={clickHandler}>アクションによる画面遷移</button>
    </>
  );
}

export async function getServerSideProps({ query }) {
  return {
    props: { query },
  };
}

スクリーンショット 2023-06-24 21.50.33.png

実行結果
ezgif.com-video-to-gif (11).gif

第二引数に対して例えば/dummy-urlと置くと、表示されるページはTOPページだが、URLのパスはhttp://localhost:3000/dummy-url このダミーURLになる。

src/pages/blog-router/[name]/setting.js
import { useRouter } from "next/router";

export default function Setting({ query }) {
  const router = useRouter();
  const clickHandler = () => {
    router.push('/','/dummy-url')
  }
  return (
    <>
      <h1>routerから取得:{router.query.name}</h1>
      <button onClick={clickHandler}>アクションによる画面遷移</button>
    </>
  );
}

// http://localhost:3000/dummy-url

export async function getServerSideProps({ query }) {
  return {
    props: { query },
  };
}

実行結果
スクリーンショット 2023-06-24 21.56.41.png

補足
pushをreplaceに変換すると、現在表示されている履歴が上書きされる。
そのため、ブラウザバックを押すと先ほどの前に開いていた画面が表示される。

  const clickHandler = () => {
    router.replace('/','/dummy-url')
  }

ezgif.com-video-to-gif (12).gif

5.Linkを使って画面遷移を行う

Reactの画面でリンクを置いて画面遷移を行う場合はリンクコンポーネントを使用します。

src/pages/index.js
import Link from "next/link"

export default function Home() {
  return (
    <>
      <h1>Home</h1>
      <Link href="/blog-router">
        <a>blog-router</a>
      </Link>
    </>
  );
}

// http://localhost:3000/

スクリーンショット 2023-06-25 1.36.01.png

実行結果
ezgif.com-video-to-gif (13).gif

補足
<a href="/blog-router">blog-router</a>
これだと画面が更新され、リロードが走る。

Linkタグで囲むと、画面遷移が発生しない。

routerと一緒でasを利用して仮想のURLを画面上で表示することも可能です。
例えばas="/dummy-url"とすると、画面上では/dummy-urlに飛ぶが、リンクを押して遷移する先はこれまで通りblog-routerになる。

src/pages/index.js
import Link from "next/link"

export default function Home() {
  return (
    <>
      <h1>Home</h1>
      <Link href="/blog-router" as="/blog-dummy">
        <a>blog-router</a>
      </Link>
    </>
  );
}

// http://localhost:3000/

hrefはオブジェクト形式で書くことも可能です。オブジェクトで書く場合にはpathnameのところに遷移させたいURLを記載し、queryも指定することで、URLの末尾にクエリパラメーターをつけることができます。

src/pages/index.js
import Link from "next/link"

export default function Home() {
  return (
    <>
      <h1>Home</h1>
      <Link href={{ pathname: "/blog-router", query: { key: "value" } }}>
        <a>blog-router</a>
      </Link>
    </>
  );
}

// http://localhost:3000/

スクリーンショット 2023-06-25 1.51.01.png

実行結果
ezgif.com-video-to-gif (15).gif

6.ページをまたぐ状態の保持の方法

下記のコードを実行します。
ボタンがクリックされると、routerのpushメソッドが呼ばれて画面遷移が発生します。その時のパスはgoToStep関数の第二引数で設定した/personalで表示されますが、実体としては/multipage?step=${step}このパスになります。

src/pages/multipage/index.js
import { useRouter } from "next/router";

export default function Multipage() {
  const router = useRouter();

  // URLで渡されたパラメーターを取得
  // stepがついてこなかった場合(nullまたはundefind)は初期値を0にする
  const step = router.query.step ?? 0;

  // 渡ってきたステップの値をパラメーターのステップの値として設定
  const goToStep = (_step, asPath) => {
    router.push(`/multipage?step=${_step}`, asPath);
  };
  
  return (
    <div>
      {step == 0 && (
        <>
          <h3>Step:{step}</h3>
          {/* ボタンがクリックされたときに次のステップに遷移する */}
          <button onClick={() => goToStep(1, "/personal")}>Next Step</button>
        </>
      )}
      {step == 1 && (
        <>
          <h3>Step:{step}</h3>
          <button onClick={() => goToStep(2, "/comfirm")}>Next Step</button>
        </>
      )}
      {step == 2 && (
        <>
          <h3>Step:{step}</h3>
          {/* 最後のボタンを押した時はstep==0のページの戻る */}
          <button onClick={() => goToStep(0, "/multipage")}>Next Step</button>
        </>
      )}
    </div>
  );
}

スクリーンショット 2023-06-25 2.32.32.png

実行結果

ezgif.com-video-to-gif (16).gif

step:0 http://localhost:3000/multipage
step:1 http://localhost:3000/personal
step:2 http://localhost:3000/comfirm

ボタンをクリックすると遷移できるようになりましたが、上記はあくまでダミーのパスであり、単体でアクセスすることはできません。

スクリーンショット 2023-06-25 2.40.06.png

このような時に、このパスを直接指定された時に動かすために、リライトという仕組みを用いることがあります。
next.config.jsにrewritesという設定を追加します。
今回の場合では、/personalというパスにリクエストが来た時にdestinationに記載されたパスのコンポーネントを動かすことができます。

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  async rewrites() {
    return [
      {
        source: "/personal",
        destination: "/multipage?step=1"
      },
      {
        source: "/comfirm",
        destination: "/multipage?step=2"
      }
    ]
  }
}

module.exports = nextConfig

サーバを一度再起動すると、直接アクセスすることが可能になりました。

ezgif.com-video-to-gif (17).gif

まとめ

プロジェクト構成

  • /pages
    ファイルまでのパスがそのままページになる
  • styles
    グローバルに適用されるスタイルを配置
  • /pages/_app.js
    ページ遷移時に必ず呼ばれる処理を記述
  • next.config.js
    Next.jsの設定を記載

ルーティング

  • pages配下からexportされたコンポーネントを1ページとしてルーティングする
  • [id]は動的なパスとして認識される
  • getServerSideProps
    queryでダイナミックルートを取得する

ページ遷移

  • useRouter
    ページ遷移を行うための値やメソッドを取得する際に利用

  • Link href
    hrefに遷移先のURLを設定する

参考

【2023年最新】React(v18)完全入門ガイド|Hooks、Next.js、Redux、TypeScript(CodeMafia)

8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5