0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

NextTopLoaderが表示されない

Last updated at Posted at 2025-09-26

Next.jsでプログラマティックなナビゲーション時にローディングバーを表示する方法

はじめに

Next.jsでアプリケーションを開発していると、ページ遷移時にユーザーに視覚的なフィードバックを提供したいケースがあります。特に、Link コンポーネントを使用せずに router.push() などでプログラマティックにナビゲーションする場合、ローディングインジケーターが表示されないことがあります。

この記事では、Next.jsアプリケーションで nextjs-toploader (NextTopLoader) を使用して、プログラマティックなナビゲーション時にもローディングバーを表示する方法について解説します。

問題: Link以外のナビゲーションでローディングバーが表示されない

通常、Next.jsの <Link> コンポーネントを使ってページ間を移動する場合、NextTopLoaderは自動的にページ遷移を検知してローディングバーを表示します。しかし、以下のようなケースではローディングバーが表示されないことがあります:

  • router.push()router.replace() を使用したプログラマティックなナビゲーション
  • フォーム送信後のリダイレクト
  • ボタンクリックやその他のイベントハンドラーからのナビゲーション

解決策: useTopLoader フックの活用

nextjs-toploader パッケージが提供する useTopLoader フックを使うことで、この問題を解決できます。このフックを使って手動でローディングバーの開始と終了を制御しましょう。
nextjs-toploader定義

実装方法

1. NextTopLoaderの設定

layout.tsx ファイルでNextTopLoaderを設定します:

'use client';

import { NextTopLoader } from 'nextjs-toploader';
import { ReactNode } from 'react';

export default function RootLayout({ children }: { children: ReactNode }) {
  return (
    <html lang="ja">
      <body>
        <NextTopLoader 
          color="#2299DD"
          initialPosition={0.08}
          height={3}
          showSpinner={false}
        />
        {children}
      </body>
    </html>
  );
}

2. useTopLoader フックの使用

プログラマティックなナビゲーションを行うコンポーネントで useTopLoader フックを使用します:

'use client';

import { useTopLoader } from 'nextjs-toploader';
import { useRouter } from 'next/navigation';
import { Button } from '@/components/ui/button'; // 例としてのUIコンポーネント

export default function NavigationExample() {
  const router = useRouter();
   const { start, done } = useTopLoader()

  const handleNavigation = async () => {
    // ローディングバーの開始
    start();
    
    try {
      // 何らかの非同期処理(APIリクエストなど)
      await someAsyncFunction();
      
      // 処理が完了したらページ遷移
      router.push('/destination-page');
      
      // Note: router.push()後はコンポーネントがアンマウントされるため、
      // 通常はdone()は不要です
    } catch (error) {
      // エラーが発生した場合はローディングを停止
      done();
      console.error('Navigation error:', error);
    }
  };

  return (
    <div>
      <h1>プログラマティックナビゲーションの例</h1>
      <Button onClick={handleNavigation}>ページ遷移</Button>
    </div>
  );
}

注意点

  1. useTopLoader フックは 'use client' ディレクティブを使用したクライアントコンポーネント内でのみ使用できます。

  2. ページ遷移が成功した場合、通常はコンポーネントがアンマウントされるため、done() を明示的に呼び出す必要はありません。エラー処理時のみ呼び出すことを推奨します。

  3. 非同期処理がない単純なナビゲーションの場合は、以下のように簡略化できます:

const handleClick = () => {
  start();
  router.push('/some-page');
};
0
0
5

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?