おはこんばんちは、ちーずです。
記念すべき10日目の記事は、「LinkコンポーネントとuseRouter」に関してです!
next/router
next/router
は、routerオブジェクトにアクセスするためのパッケージです。
useRouter
と withRouter
(とそれらの型)をexportしていますが、
- 関数Component → useRouter
- クラスComponent → withRouter
と覚えておけばOKです。
両方とも、routerオブジェクトが返されます。
routerオブジェクト
基本的にはNext.jsに最適化されたwindow.location
やwindow.history
みたいなもので、
url関連の情報を取得・操作するための処理が含まれています。
下記のような構造のrouterオブジェクトの例をみてみましょう。
例 | |
---|---|
(next.config.jsで設定した) basePath | /tech |
ページComponentのディレクトリ | /pages/blogs/[code].ts |
ページURL | https://example.com/tech/blogs/nextjs?page=3 |
このようなケースのrouterオブジェクトの値はこのようになります。(※よく使うもののみ)
pathname : '/blogs/[code]', // page配下のディレクトリ
query : { code: 'nextjs', page: '3' }, // 動的ルーティングのパラメータと、クエリパラメータ のオブジェクト
basePath : '/tech', // basePath
asPath : '/blogs/nextjs?page=3' // basePathを以降のURL
※ ハッシュを取得したい場合、useHash
にasPath
を渡してあげましょう。
次によくつかうメソッドを紹介します。
router.push
クライアント側の遷移処理をおこないます。
基本的な書き方は、router.push(url, as, options);
です。
push(url: Url, as?: Url, options?: TransitionOptions): Promise<boolean>;
asは基本undefinedで良いです。(9.5.3前のデコレーター)
また、optionsの型は下記になります。
interface TransitionOptions {
shallow?: boolean; // 浅いルーティングにするか (デフォは false)
locale?: string | false; // 新しいページのロケール設定
scroll?: boolean; // 遷移後に先頭にスクロールするか (デフォはtrue)
}
shallowルーティングとは、 getStaticProps や getServerSideProps を実行せずにURLの変更することです。
また、URLオブジェクトを引数に渡すこともできます。
router.push({
pathname: '/blog',
query: { code: 'nextjs' }
});
router.replace
履歴に追加せずに、遷移処理をおこないます。
型はrouter.push
と全く一緒です。
Router.replace('/blog');
router.back
履歴を1つ戻します。(ブラウザバック、戻るボタンクリックと同じ挙動)
window.history.back()
と同様。
router.reload
リロード(更新)します。
window.location.reload()
と同様。
router.events
URLやハッシュの変更を検知して、処理を実行できます。
-
beforeHistoryChange
: ブラウザの履歴を変更する直前 -
routeChangeComplete
: ルートが完全に変更され終わったとき -
hashChangeComplete
: ハッシュの変更が完了した時
などがあります。
next/link
Linkコンポーネントを返すパッケージです。
import Link, { LinkProps } from 'next/link';
export const Navigation = () => (
<Link href="/">
<a>トップに戻る</a>
</Link>
)
Linkコンポーネントには下記のPropsがあります。
export declare type LinkProps = {
href: Url; // URL もしくは pagesディレクトリ内のパス
as?: Url; // ブラウザのURLバーに表示されるパス (動的ルーティング用)
replace?: boolean; // 履歴に追加せずに、遷移処理をするか (デフォ false)
scroll?: boolean; // 遷移後に先頭にスクロールするか (デフォはtrue)
shallow?: boolean; // 浅いルーティングにするか (デフォは false)
passHref?: boolean; // 子にhrefプロパティを送るか (デフォは false)
prefetch?: boolean; // バックグラウンドでページをプリフェッチするか (デフォは true)
locale?: string | false; // 新しいページのロケール設定
};
動的ルーティングの際の記述方法
先ほど使ったこのページに遷移するLinkコンポーネントを作成したい場合
例 | |
---|---|
ページComponentのディレクトリ | /pages/blogs/[code].ts |
ページURL | `https://example.com/tech/blogs/nextjs |
2パターンの書き方があります。
// 1. hrefにpathnameを渡す方法
const Navigation1 = () => (
<Link href='/blogs/[code]' as='/blogs/nextjs' passHref>
<a>Hi! Next.js</a>
</Link>
)
// 2. hrefにURLオブジェクトを渡す方法
const Navigation1 = () => (
<Link href={{ pathname: '/blogs', query: { code: 'nextjs' }}} passHref>
<a>Hi! Next.js</a>
</Link>
)
passHref
とは?
passHref
は、子要素のaタグにhrefを渡すプロパティです。
基本的に、子要素がaタグの時は必ず設定しましょう。
(設定しないと、空のaタグになっていまい、SEOに悪影響を及ぼす可能性がございます。)
const Navigation3 = () => (
<Link href='/blogs/[code]' as='/blogs/nextjs' passHref>
<a>Hi! Next.js</a>
</Link>
)
// 出力すると、 <a href="/blogs/nextjs">Hi! Next.js</a> みたいになる
子要素が<a>
以外の時
そのような時は、onClick
でユーザーの遷移処理 (処理でいうと router.push) を実行します。
href属性はなくなってしまうため、HTMLの構造上リンクであると伝えたい時は、
なるべく<Link>
の直下は aタグ もしくは 一番親要素がaタグのコンポーネント を使いましょう。
以上、<Link>
と useRouter
についてでした!