注: Next9.5.3以降は必要なくなりました!!!hrefのみで正しくルーティングされます。
Next.jsでのルーティングはLink
コンポーネントで行うが、正しく使わないとクライアントサイドでルーティングが行われない。
もちろんDocに書いてあるのだが、先日までハマっていたので共有。
環境
- Nextjs 9.3.4
確認
ChromeやFirefoxの拡張機能、React Developer Tools
を用いてコンポーネントのレンダリング状況を確認すると、クライアントサイドでルーティングされているかを確認できる。
以下は自作ブログでの例。
- クライアントサイドルーティングが正しく行われていない場合。
コンポーネントがすべてアンマウントされ、再レンダリングされてしまっている。
- クライアントサイドルーティングが正しく行われている場合
共通部分のコンポーネントはアンマウントされず、ページコンポーネントだけがレンダリングされている。
正しいリンク
aタグでの遷移
Linkコンポーネントで、aタグをラップする。
aタグにはhrefを指定しない。
Linkコンポーネントは実際にはレンダリングされないので、HTML上ではaタグのみになる。
import Link from 'next/link';
import React from 'react';
export const anchorLink: React.FC = () => {
return (
<Link href="/">
<a>To TOP</a>
</Link>
);
};
他タグでの遷移
buttonタグやimgタグでも同様だが、passHrefをtrueにしておく。
passHref=true
のLinkコンポーネントは、直下のコンポーネントがonClickを受け取る場合、遷移アクションを渡す。
import Link from 'next/link';
import React from 'react';
export const buttonLink: React.FC = () => {
return (
<Link href="/" passHref>
<Button>To TOP</Button>
</Link>
);
};
動的URLでの遷移
ここがハマりやすいポイント。
Next.jsでは、pages/post/[id].tsx
とすると、/post/1
,/post/2
のような動的ルーティングを行える。
このとき、正しくLinkコンポーネントにPropsを渡さないと、クライアントサイドでのルーティングは行えない。
pages/post/[id].tsx
のページに遷移する場合、以下ではクライアントサイドでルーティングされない。
import Link from 'next/link';
import React from 'react';
export const dynamicLink: React.FC = () => {
return (
<Link href="/post/1">
<a>To Post 1</a>
</Link>
);
};
以下が正しい例。
hrefには、pagesディレクトリ内の遷移先ファイルと同様に記述し、asで実際の値を渡す。
pages/post/[postId].tsx
の場合、href="/post/[postId]"
とする。
import Link from 'next/link';
import React from 'react';
export const dynamicLink: React.FC = () => {
return (
<Link href="/post/[id]" as="/post/1">
<a>To Post 1</a>
</Link>
);
};
一部の記事では、「LinkコンポーネントのasはブラウザのURLバーに表示するアドレスを変更できる」旨を記述されているため、
それだけの効果だと思いがちだが、それだけではないようだ。(それだけの効果だと思っていた。)
とりあえず公式Docは目を通しましょう。