Next.js と TypeScript で、useRouterを学ぶ

TwitterFacebookHatena

TL;DR

この記事では Next.js の useRouter フックの使い方を TypeScript を用いて詳細に説明します。このフックを理解し使いこなすことで、あなたのアプリケーションはよりダイナミックで使いやすくなるでしょう。

開発環境 バージョン
Next.js 13.4.3
TypeScript 5.0.4
Emotion 11.11.0
React 18.2.0

useRouter フックとは?

useRouterは Next.js に組み込まれている特別なフックで、ルーティングに関連する情報にアクセスするために使われます。具体的には、現在のページの URL、クエリパラメータ、ルーティングメソッドなどにアクセスできます。

これを使って、Google Analytics を設定したり、問い合わせフォームを送信した後に特定のページにリダイレクトしたりすることができます。

useRouterは、ウェブサイトの中で移動するための地図のようなものです。例えば、家の中で部屋から部屋へ移動するときに、どの部屋に行くかを知るために地図を使うようなイメージです。

useRouterを使うと、ウェブサイトのどのページにいるのか、または別のページに移動するときにどの道を通るべきかを知ることができます。それによって、ウェブサイトの中でスムーズに移動することができます。

どのようなときに使うのか?

例えば、どのようなときに使うのか?というと

  • フォームの送信後に特定のページにリダイレクトする
  • ページの移動が終わったときに Google Analytics のページビューイベントを送信する
  • ユーザーが認証されていない場合や特定の条件を満たしていない場合に、ログインページやエラーページにリダイレクトする
  • 現在の URL パスを取得し、それを基にパンくずリストを生成する
  • アクセス制御や認証
  • URL パラメータに基づいて特定の商品や記事を表示する
  • 404 ページにリダイレクトする

といった場合に使うことができます。

用語解説

次に、主要な用語を表形式でまとめます。

用語 説明
useRouter Next.js の機能で、ウェブサイト内での移動を管理するもの
router object useRouterが提供するオブジェクトで、現在のページの情報やページ間の移動方法を提供
pathname 現在のページのパス(例:/about)
query URL のクエリパラメータ(例:?id=123)
asPath ブラウザに表示されるパス
push 新しいページに移動するためのメソッド
replace 現在のページを新しいページで置き換えるためのメソッド
back 前のページに戻るためのメソッド
reload 現在のページを再読み込みするためのメソッド
events ページの移動が始まったときや終わったときなど、ルーターの状態が変わったときに発生するイベント

Functions: useRouter | Next.jsに書かれているコードを解説します。

import { useRouter } from 'next/router'

function ActiveLink({ children, href }) {
  const router = useRouter()
  const style = {
    marginRight: 10,
    color: router.asPath === href ? 'red' : 'black',
  }

  const handleClick = (e) => {
    e.preventDefault()
    router.push(href)
  }

  return (
    <a href={href} onClick={handleClick} style={style}>
      {children}
    </a>
  )
}

export default ActiveLink

このコードは、Next.js のuseRouterを使ってリンクを作る例です。ActiveLinkという関数は、子要素(children)とリンク先の URL(href)を受け取り、そのリンクを表示します。リンクの色は、現在のページがリンク先と同じであれば赤色、そうでなければ黒色になります。

handleClick関数は、リンクがクリックされたときに呼び出されます。この関数は、デフォルトのリンクの動作を止めて(e.preventDefault())、代わりにrouter.push(href)を使って新しいページに移動します。これにより、Next.js のページ間移動の機能を利用することができます。

最後に、このActiveLink関数をデフォルトでエクスポートしています。これにより、他のファイルからこの関数をインポートして使うことができます。

次のコードは、Next.js のuseRouterフックを使って、ボタンをクリックしたときに特定のページ(この場合は'/about'ページ)に移動する機能を持つコンポーネントを作成しています。

import { useRouter } from 'next/router'

export default function Page() {
  const router = useRouter()

  return (
    <button type="button" onClick={() => router.push('/about')}>
      Click me
    </button>
  )
}

const router = useRouter(); は、useRouterフックを呼び出して、ルーターオブジェクトを取得しています。このルーターオブジェクトを使って、ページ間の移動を制御します。

<button type="button" onClick={() => router.push('/about')}> は、ボタンを定義しています。このボタンは、クリックされたときにrouter.push('/about')を実行します。router.push('/about')は、'/about'ページに移動する命令です。

useRouter フックの使い方

それでは、簡単な useRouter の使用例を見てみましょう。

// ファイル名: pages/index.tsx

import { useRouter } from 'next/router'

type Props = {
  text: string
}

const Page = ({ text }: Props) => {
  const router = useRouter()
  console.log(router.pathname) // 現在のページのパスが表示される

  return <div>{text}</div>
}

export default Page

ここでは、useRouter フックを用いて現在のページのパスをコンソールに出力しています。同様に、router.query を使用することで URL のクエリパラメータにアクセスすることができます。

Next.js のLinkコンポーネントとuseRouterフックは、どちらもページ間の移動を制御するためのツールですが、使い方と機能にはいくつか違いがあります。

Linkコンポーネントは、主に静的なリンクを作成するために使用されます。つまり、リンク先の URL が固定で、クリックするだけで特定のページに移動するようなリンクを作るときに使います。Linkコンポーネントは、自動的に<a>タグを生成し、Next.js のページ間移動の機能を利用します。

一方、useRouterフックは、より動的なページ間の移動を制御するために使用されます。例えば、ユーザーのアクションに基づいてリンク先を決定したり、プログラム的にページを移動したりするときに使います。useRouterは、ルーターオブジェクトを提供し、そのオブジェクトのメソッド(pushreplaceなど)を使ってページ間の移動を制御します。

先程の例では、ボタンがクリックされたときに特定のページ('/about'ページ)に移動するという動的な動作を制御しています。このような場合、useRouterpushメソッドを使ってページ間の移動を制御することができます。

したがって、LinkコンポーネントとuseRouterフックの主な違いは、Linkが静的なリンクを作成するのに対し、useRouterが動的なページ間の移動を制御するために使用されるという点です。

問い合わせフォームを作成

動的な遷移の例として、Next.js で問い合わせフォームを作成し、フォームが送信された後にユーザーを'thanks'ページにリダイレクトする例を書きます。

import { useRouter } from 'next/router'
import { useState } from 'react'

export default function ContactForm() {
  const router = useRouter()
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    message: '',
  })

  const handleChange = (e) => {
    setFormData({ ...formData, [e.target.name]: e.target.value })
  }

  const handleSubmit = async (e) => {
    e.preventDefault()
    // ここでフォームデータをAPIに送信する処理を行います。
    // 例: await fetch('/api/contact', { method: 'POST', body: JSON.stringify(formData) });

    // フォーム送信後に'thanks'ページにリダイレクトします。
    router.push('/thanks')
  }

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="name" value={formData.name} onChange={handleChange} placeholder="Your Name" required />
      <input type="email" name="email" value={formData.email} onChange={handleChange} placeholder="Your Email" required />
      <textarea name="message" value={formData.message} onChange={handleChange} placeholder="Your Message" required />
      <button type="submit">Submit</button>
    </form>
  )
}

このコードでは、React のuseStateフックを使ってフォームデータを管理し、useRouterフックを使ってフォーム送信後のリダイレクトを制御しています。また、各フォームフィールドのonChangeイベントハンドラを使って、ユーザーが入力したデータをformDataステートに保存しています。

handleSubmit関数は、フォームが送信されたときに呼び出されます。この関数では、まずe.preventDefault()を呼び出してフォームのデフォルトの送信動作を止め、次にフォームデータを API に送信する処理を行います。最後に、router.push('/thanks')を呼び出してユーザーを'thanks'ページにリダイレクトします。

このコードはあくまで一例であり、実際のアプリケーションでは API への送信処理やエラーハンドリングなどを適切に実装する必要があります。

Next.js と TypeScript で、useRouterを学ぶ