🐈

Next.jsのバージョン15.3が出たんじゃ

に公開

初めに

この記事が公開されることには私は一歳年を重ねるでしょう!バースデーイイねをお待ちしています!!!!!
さてNext.js使いの皆さん、Next.jsがバージョンアップしましたね〜
主に5つの機能がアップデートしました。

ナビゲーションフックについて

さて本当にナビゲーションフックについてしか書きませんので、他の項目に興味がある方はここまでで止めた方がいいです!

  • onNavigate
  • useLinkStatus

今回のアプデートでは上記2つが新たに追加されました。そしてどちらもかなり使いそうなフックなので一緒に学んでいきましょう!

onNavigate

このイベントハンドラーはLinkコンポーネントの新しいプロパティであり、クライアント側のナビゲーション中に実行され、アプリケーションのルーティング動作を正確に制御できます。
onClickすべてのクリックに対して発生するイベントとは異なり、onNavigateはシングルページアプリ(SPA)で使用できます。ナビゲーションにより、コードを実行したり、preventDefault()でナビゲーションをキャンセルしたりすることもできます。
この API を使用すると、実際のページ遷移時にのみ実行される遷移アニメーション、ナビゲーション ガード、または分析トラッキングを実装できます。
下記のコードは公式から抜粋しました。

import Link from 'next/link'
 
export default function Page() {
  return (
    <Link
      href="/dashboard"
      onNavigate={(e) => {
        // Only executes during SPA navigation
        console.log('Navigating...')
 
        // Optionally prevent navigation
        // e.preventDefault()
      }}
    >
      Dashboard
    </Link>
  )
}

例えば、権限を判定して、権限次第でこのページには遷移できないようにさせるとか、dashboardに遷移する際にログインしているユーザーかどうか判定して、ログインしているユーザーなら遷移させる。ログインしていなかったら、ダッシュボードに遷移させないみたいなことができそうですね!

'use client';

import Link from 'next/link'
import { use } from 'react';
import { useUser } from '@/lib/auth';

export default function ActivityPage() {
  const { userPromise } = useUser();
  const user = use(userPromise);

  return (
    <section className="flex-1 p-4 lg:p-8">
      <h1 className="text-lg lg:text-2xl font-medium mb-6">Activity</h1>
      <Link 
        href="/dashboard"
        onNavigate={(e) => {
          console.log('Navigating to dashboard');
          if (!user) {
            alert('ログインしていないため、遷移できません');
            e.preventDefault();
            redirect('/login');
          }
          return true;
        }}
      >Go to Dashboard
      </Link>
    </section>
  );
}

こちらは「ログインしているユーザーでなければダッシュボードに遷移させずに、ログイン画面に遷移」という処理の実装例です。

  if (!user) {
    redirect('/login');
  }

正直、上記のような早期リターンで返した方が早いのではとも思っていますが、下記の処理だとそもそも画面が開けないので、どんな画面かもわからないですね。

  { user && (
    ~~~~~(省略)
  )}

これでも対応できそうですが、遷移できるボタン(実際のコードと異なりますが、ボタンの方がイメージつくと思うので、ボタンとします)が消えてしまいます。例えば、権限によって表示されるボタンがあるとかの場合、ユーザー的にはわからないですよね…
権限によらずボタンが表示されて「権限ないぞ」ってメッセージが出た方がわかりやすいですよね〜

useLinkStatus

このuseLinkStatusフックを使用すると、Linkの保留状態を追跡できます。新しいルートへのナビゲーションが完了するまでの間、ユーザーにインラインの視覚的なフィードバック(スピナーやテキストグリマーなど)を表示できます。
注意点

  • useLinkStatusはLinkコンポーネントの子孫コンポーネント内で使用する必要があります
  • このフックはLinkコンポーネントprefetch={false}に設定されている場合に最も役立ちます
  • リンクされたルートがプリフェッチされている場合、保留状態はスキップされます
  • 複数のリンクを連続してクリックすると、最後のリンクの保留状態のみが表示されます
  • このフックはページルータではサポートされていないため、{ pending: false }を常に返されます
  • パラメーターは不要

じゃ早速公式の例を見てみましょう!

app/loading-indicator.tsx
'use client'
 
import { useLinkStatus } from 'next/link'
 
export default function LoadingIndicator() {
  const { pending } = useLinkStatus()
  return pending ? (<span>⌛️</span>) : null
}
app/header.tsx
import Link from 'next/link'
import LoadingIndicator from './loading-indicator'
 
export default function Header() {
  return (
    <header>
      <Link href="/dashboard" prefetch={false}>
        Dashboard <LoadingIndicator />
      </Link>
    </header>
  )
}

ところで、prefetch={false}って何?って方向けに少し雑談
Next.jsのprefetchは、リンクが表示される前にページのコンテンツを事前に読み込んでおく機能です。これにより、ユーザーがリンクをクリックした際のページ遷移がより速くなります。
具体的には、Linkコンポーネントにprefetch={true}を設定すると、そのリンク先のページデータがバックグラウンドで事前に読み込まれます。これにより、ユーザーがリンクをクリックした際にはすでにページがキャッシュされているため、遷移が速く感じられます。Next.jsは、リンクが表示された時点でそのリンク先を予測して、事前に読み込みを行います。
一方、prefetch={false}を設定すると、リンク先のページを事前に読み込まないようにすることができます。この設定は、ページ遷移のパフォーマンスをコントロールしたり、不要なリソースの読み込みを避けたりするために使われることがあります。
じゃprefetch={true}にした方が良いじゃんと思いますが、じつはVercelの裏側の機能を使用するのでこれお金かかるんです…
具体的な金額はわからないので、いくらになるかわからないですが基本的にprefetch={false}で良いんじゃないかなと思います。

最後に

この記事が誰かの役に立てば幸いです

GitHubで編集を提案

Discussion