🦾

Next.js (2): Routing / App Component

2022/03/15に公開

Routing

a タグのhrefを利用するとESlintでエラーになります。この方法だとページをリロードさせるので遅くなるからという警告してくれています。

aタグにhrefを利用しないで<Link>で囲む形で使います。
LinkにclassNameなどは使えないため、下位の<a>タグに入れます。

import Link from "next/link";

export default function NavBar() {
  return (
    <nav>
      <Link href="/">
        <a className='hello'>HOME</a> // a tagに追加
      </Link>
      <Link href="/about">
        <a>About</a>
      </Link>
    </nav>
  );
}

useRouter hook

https://nextjs.org/docs/api-reference/next/router
routerオブジェクトにアクセスするためのhookです。

例えばrouter.pathnameを使うと、現在の場所が取得できます。
以下のソースコードはpathnameを確認してlinkの色を変えています。

import Link from "next/link";
import { useRouter } from "next/router";

export default function NavBar() {
  const router = useRouter();
  return (
    <nav>
      <Link href="/">
        <a style={{ color: router.pathname === "/" ? "red" : "blue" }}>HOME</a>
      </Link>
      <Link href="/about">
        <a style={{ color: router.pathname === "/about" ? "red" : "blue" }}>
          About
        </a>
      </Link>
    </nav>
  );
}

aboutページに行くとnavのAboutリンクは赤く、HOMEリンクは青くしています。

App Component

https://nextjs.org/docs/advanced-features/custom-app

メイン画面とabout画面にヘッダーのようなnavigation barを表示したい場合、メイン画面とabout画面の両componentにnavigation componentを追加する必要はありません。

Next.jsはApp componentを利用してページの初期化していますが、_app.jsはそれを上書きできるcomponentです。pages/_app.jsを以下の内容で作成します。

ファイル名は_appにする必要があるが、component名は自由につけて大丈夫です。

pages/_app.js

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

export default MyApp

そしてNavBar componentとglobalなcssも追加してみました。これで全ページに反映されます。
他のcomponentを呼び出すときに、_app.jsに書いてあるのも追加でreturnしてあげる仕組みです。

pages/_app.js
import NavBar from "../components/NavBar";
import "../styles/globals.css";

export default function MyApp({ Component, pageProps }) {
  return (
    <>
      <NavBar />
      <Component {...pageProps} />
      <style jsx global>{`
        a {
          color: lime;
        }
      `}</style>
    </>
  );
}

Dynamic Router

movies/123123 のようにid(ここだと映画のid)によって詳細ページに遷移させたい場合、idをファイル名にすることで渡せます。[]で囲む必要があります。

  • 例)pages/movies/[id].js
pages/movies/[id].js
import { useRouter } from "next/router";

export default function Detail() {
  const router = useRouter();
  console.log(router);

  return "detail";
}

routerの中にqueryとして渡したidが入っています。

  • query: id :'1'

[hoge]でファイル名を作った場合、hogeがkeyになります。

  • 例) {hoge:123123}

useRouter.push

useRouter.push(url , as?:url)

routerのpushを使うと、上記のqueryを利用してurlでコンポーネントにパラメータを渡すことができます。
一番目の引数にはpathnameを使って遷移したいurlを書き、渡したいパラメータをqueryに書きます。
以下の例でonclickを発動させたときに、

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

const router = useRouter();
const onClick = (id, title) => {
    router.push(
      {
        pathname: `/movies/${id}`, // 引数1
        query: {
          title,
        },
      },
    );
  };
  
// 省略

このようなURLに遷移されます。
http://localhost:3001/movies/634649?id=634649&title=spiderman

ここでurlをもっと綺麗にしたい場合にrouterのpushの引数2を使い、遷移させたいurlを書きます。
以下の例だと

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

const router = useRouter();
const onClick = (id, title) => {
    router.push(
      {
        pathname: `/movies/${id}`,
        query: {
          title,
        },
      },
      `/movies/${id}`  //引数2
    );
  };
  
// 省略

このようなURLになります
http://localhost:3001/movies/634649

onClickして遷移されるページは以下のようにかけます。router.queryの中にidとtitleを受け取れます。

pages/movies/[id].js
import { useRouter } from "next/router";

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

  return (
    <div>
      <h4>{router.query.title}</h4>
    </div>
  );
}

Discussion