LoginSignup
21
25

More than 3 years have passed since last update.

Next.js 9にDynamic Routingが付いた、それは嬉しい

Last updated at Posted at 2019-07-07

概要

Next.jsに、ダイナミックルートがあれば良いなあって前々から思っていたけど、Next 9見ていたら増えていたわ。

環境

package.json
{
  "dependencies": {
    "next": "^9.0.0",
    "react": "^16.8.6",
    "react-dom": "^16.8.6"
  },
  "devDependencies": {
    "@types/node": "^12.6.1",
    "@types/react": "^16.8.23",
    "prettier": "^1.18.2",
    "typescript": "^3.5.2"
  }
}

DynamicRouteの使い方

基本的には、ディレクトリ名やファイル名を[fugafuga]/[fugafuga].jsxにするとそこに反応するようになる。

.
├── pages
│   ├── hoge.tsx
│   ├── index.tsx
│   └── kani
│       ├── [kaniname]
│       │   ├── description
│       │   │   ├── [kanitips].tsx
│       │   │   ├── hoge.tsx
│       │   │   └── index.tsx
│       │   └── index.tsx
│       ├── hoge.tsx
│       └── index.tsx

例えばこのようなフォルダ構成だとする。フォルダ名に"["と"]"がついているので、かなり異様。

3例をほど

  • localhost:3000/kani/hoge/にアクセスすると ->pages/kani/hoge.tsxが読み込まれる。

  • localhost:3000/kani/piyoにアクセスすると ->pages/kani/[kaniname]/index.tsxが読み込まれる。

これは大変ありがたい。

localhost:3000/kani/piyo にアクセスされた時に、pages/kani/[kaniname]/index.tsx において、useRouterフックを使うとその中のkaninameパラメタにpiyoが入っている。

const KaniName: NextPage = () => {
  const router = useRouter();
  const { kaniname } = router.query;
  return <p>{kaniname}</p>;
};
export default KaniName;

スクリーンショット 2019-07-08 2.11.15.png


  • localhost:3000/kani/piyo/description/にアクセスすると ->pages/kani/[kaniname]/description/index.tsxが読み込まれる。
  • localhost:3000/kani/piyo/piyopiyo/にアクセスすると ->404になる

  • localhost:3000/kani/piyo/description/hogeにアクセスすると ->pages/kani/[kaniname]/description/hoge.tsxが読み込まれる。
  • localhost:3000/kani/piyo/description/piyopiyoにアクセスすると ->pages/kani/[kaniname]/description/[kanitips].tsxが読み込まれる。

こんな感じのデータがあるとして

export interface Kani {
  name: string;
  description: string;
  tips: { title: string; content: string }[];
}
export const kanis: Kani[] = [
  {
    name: "カニ一郎",
    description: "強いカニ",
    tips: [
      { title: "強さの秘密", content: "強いから" },
      { title: "生まれ", content: "琵琶湖" }
    ]
  },
  {
    name: "カニ二郎",
    description: "さらに強いカニ",
    tips: [{ title: "生まれ", content: "太平洋" }]
  },
  {
    name: "カニ三郎",
    description: "さすらいのカニ",
    tips: []
  }
];

こんかな感じで動的にページを作れる。

pages/kani/[kaniname]/description/[kanitips].tsx
const KaniTips: NextPage = () => {
  const router = useRouter();
  const { kaniname, kanitips } = router.query;
  const [kani] = useState(kanis.find(e => e.name == kaniname));

  return (
    <Layout>
      {kani ? (
        <>
          <h1>
            {kani.name}{kanitips}
          </h1>
          <hr />
          <KaniFactFind kani={kani} kanitips={kanitips} />
        </>
      ) : (
        <p>{kaniname}なる奴は知らん</p>
      )}
    </Layout>
  );
};

export default KaniTips;

スクリーンショット 2019-07-08 2.21.43.png

スクリーンショット 2019-07-08 2.25.19.png

スクリーンショット 2019-07-08 2.25.29.png

useRouteの型がanyだったので、JSON.stringifyして見るだけしてみた。あとあと詳しく調べよ思うけど、そのうち治る気がする。

routerの中をJSON.stringifyした奴
{
  pathname: "/kani/[kaniname]/description/[kanitips]",
  route: "/kani/[kaniname]/description/[kanitips]",
  query: { kaniname: "カニ五郎", kanitips: "強さの秘密" },
  asPath:
    "/kani/%E3%82%AB%E3%83%8B%E4%BA%94%E9%83%8E/description/%E5%BC%B7%E3%81%95%E3%81%AE%E7%A7%98%E5%AF%86",
  events: {}
}

今までは、ページパラメータに情報を食わせて、?やら=やらがたくさん作るURLにするか、Linkasをつけてマスクするかなかった。Linkasすると何がまずいかと言うとリロードした時に、404とかになる。

<Link href="/kani?kaniname=piyo" as="/kani/piyo">
      <a>kani/piyoへと見せかけて/kani?kaniname=piyoへ</a>
</Link>

そのためExpressなりでサーバーを立てなければならなかったが、今回のDynamic Routingが導入されれば、そのようなカスタムサーバを立てる機会が減る。(そら当然、機会が完全に0にはならんけど)

こんな感じにgetInitialPropsしてもいいか知ら。

pages/kani/[kaniname]/description/[kanitips].tsx
const KaniTips: NextPage<{ kani: Kani }> = ({ kani }) => {
  const router = useRouter();
  const { kaniname, kanitips } = router.query;
  return (
    <Layout>
      {kani ? (
        <>
          <h1>
            {kani.name}{kanitips}
          </h1>
          <hr />
          <KaniFactFind kani={kani} kanitips={kanitips} />
        </>
      ) : (
        <p>{kaniname}なる奴は知らん</p>
      )}
    </Layout>
  );
};
KaniTips.getInitialProps = async ({ query }) => {
  const { kaniname } = query;
  return { kani: kanis.find(e => e.name == kaniname) };
};
export default KaniTips;

まとめ

  • Next.js 9はDynamic Routeがついている。・・・それは嬉しい❤️
  • フォルダ名や、ファイル名に[]がつく景色が出てくるかも
  • Next.jsにExpressなり、カスタムサーバーたてる機会がもっと減って、楽チンになるかも

参考

おまけ

できた奴: https://github.com/NanimonoDemonai/dynamic-routing

なんかつくってもいない、description.jsを読みに行こうとして、ないもんだから、404とか吐いているけど、そのうち治るかな

21
25
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
21
25