Skip to content

useHistory から useNavigate への移行:React Router v6 での変更点

問題点

React Router を使用している際に、以下のようなエラーが発生する場合があります:

Attempted import error: 'useHistory' is not exported from 'react-router-dom'

このエラーは、React Router のバージョンに関連する問題です。特に、v5 から v6 へのメジャーアップデートにおいて、useHistory フックが非推奨となり、新しい useNavigate フックに置き換えられました。

解決策

方法1: React Router v6 で useNavigate を使用する(推奨)

React Router v6 では、useHistory の代わりに useNavigate を使用します。

jsx
import { useNavigate } from 'react-router-dom';

function MyComponent() {
  const navigate = useNavigate();
  
  const handleClick = () => {
    // 基本的なナビゲーション
    navigate('/home');
    
    // 置換ナビゲーション(履歴に追加しない)
    navigate('/home', { replace: true });
    
    // state を渡す場合
    navigate('/user', { state: { id: 123, name: 'John' } });
  };
  
  return (
    <button onClick={handleClick}>
      ホームへ移動
    </button>
  );
}

方法2: 履歴操作の互換性

v5 の useHistory が提供していた goBack, goForward, go メソッドも、useNavigate で実現できます。

jsx
import { useNavigate } from 'react-router-dom';

function NavigationButtons() {
  const navigate = useNavigate();
  
  return (
    <>
      <button onClick={() => navigate(-2)}>
        2ページ戻る
      </button>
      <button onClick={() => navigate(-1)}>
        戻る
      </button>
      <button onClick={() => navigate(1)}>
        進む
      </button>
      <button onClick={() => navigate(2)}>
        2ページ進む
      </button>
    </>
  );
}

方法3: React Router v5 を使い続ける場合

何らかの理由で v6 への移行が難しい場合は、v5 の最新バージョン(5.2.0以上)を使用することで useHistory を引き続き利用できます。

bash
npm install react-router-dom@5.2.0

WARNING

v5 のサポートは将来的に終了する可能性があるため、長期的には v6 への移行を検討することをお勧めします。

実装例

以下は、実際のコードで useHistory から useNavigate に移行する具体例です。

移行前 (v5):

jsx
import { useHistory } from 'react-router-dom';

function UserForm() {
  const history = useHistory();
  
  const confirm = (e) => {
    history.push('/success');
  };
  
  // ... その他のコード
}

移行後 (v6):

jsx
import { useNavigate } from 'react-router-dom';

function UserForm() {
  const navigate = useNavigate();
  
  const confirm = (e) => {
    navigate('/success');
    // または置換したい場合
    // navigate('/success', { replace: true });
  };
  
  // ... その他のコード
}

よくある使用シナリオ

jsx
async function handleSubmit(formData) {
  try {
    const result = await submitToAPI(formData);
    navigate('/success', { 
      replace: true,
      state: { message: '登録が成功しました' }
    });
  } catch (error) {
    navigate('/error', { state: { error: error.message } });
  }
}
jsx
function CheckoutProcess() {
  const navigate = useNavigate();
  const { user } = useAuth();
  
  const proceedToPayment = () => {
    if (user.isLoggedIn) {
      navigate('/payment');
    } else {
      navigate('/login', { 
        state: { from: '/checkout' } 
      });
    }
  };
  
  return (
    <button onClick={proceedToPayment}>
      決済へ進む
    </button>
  );
}

まとめ

React Router v6 では、ナビゲーションのための API が刷新され、useHistory から useNavigate へと変更されました。この変更により、コードはより直感的で一貫性のあるものになっています。新しいプロジェクトでは v6 を使用し、既存のプロジェクトについては計画的な移行を推奨します。

INFO

React Router の最新情報や詳細な移行ガイドについては、公式ドキュメントを参照してください。