【ITニュース解説】TanStack Router: Go to Previous page after Sign In
2025年09月16日に「Dev.to」が公開したITニュース「TanStack Router: Go to Previous page after Sign In」について初心者にもわかりやすく解説しています。
ITニュース概要
TanStack Routerを使用し、サインイン後に元のページへ戻れず状態が失われるUX課題を解決する。サインイン前のページに戻すため、明示的なリダイレクトと自動で直前の場所を記録する2つの方法を紹介。両者を組み合わせ、サインイン前の状態を保持したまま元のページへ戻る実装方法を解説する。
ITニュース解説
ウェブアプリケーションにおいて、ユーザーがログインが必要なページにアクセスし、サインインページに移動してログインを完了した後に、元のページではなくアプリケーションのトップページにリダイレクトされてしまうという状況は、多くのユーザーにとって不便な体験となる。例えば、ユーザーが特定のフィルターを設定した商品一覧ページを閲覧している最中にログインが必要となり、その後トップページに戻されてしまえば、それまでのフィルター設定が失われ、同じ操作を繰り返さなければならない。このようなユーザー体験(UX)の課題を解決し、ログイン後にユーザーが元のページに正確に戻れるようにするための二つの主要なアプローチを、このニュース記事は紹介している。
一つ目のアプローチは「明示的なリダイレクト」と呼ぶ方法である。これは最も直接的で信頼性の高い解決策であり、サインインページへのリンクに、ログイン後に戻るべきページのURLをredirectToという名前の検索パラメーターとして含める。検索パラメーターとは、URLの末尾に?の後に続くkey=value形式のデータのことである。例えば、https://example.com/login?redirectTo=/products?category=booksのように使用される。
このアプローチを実装するためには、まずサインインフォームのコンポーネントを設計する。このコンポーネントは、ログインが成功した際に、redirectToパラメーターで指定されたURLへとユーザーをリダイレクトする。もしredirectToが指定されていなければ、デフォルトとしてトップページ(/)へリダイレクトするように設定しておく。記事のコード例では、SignInFormコンポーネントがredirectToというプロパティを受け取り、TanStack Routerが提供するuseNavigateフック(プログラム的にページ遷移を行う機能)を使って、ログイン成功後に指定されたredirectToへ移動させる。
次に、このredirectToパラメーターがどこから来るのかを定義する必要がある。TanStack Routerでは、createFileRoute機能を使って特定のパス(例: /sign-in)に対するルート(ページ)を定義する。このルート定義の中で、validateSearchという設定を利用して、検索パラメーターの検証を行う。記事ではZodというデータ検証ライブラリを使って、redirectToという文字列型のパラメーターが存在するかをチェックし、もし存在しない場合はデフォルト値として/(トップページ)を設定している。これにより、サインインページにアクセスする際にredirectToパラメーターがなくてもエラーにならず、安全にデフォルトの挙動を保証できる。ルートコンポーネント内ではRoute.useSearch()フックを使って、この検証済みのredirectToの値を取得し、それを先ほどのSignInFormコンポーネントにプロパティとして渡している。
最後のステップは、アプリケーション内の全てのサインインページへのリンクに、このredirectToパラメーターを正しく含めることである。例えば、ヘッダー部分にあるサインインボタンの場合を考える。記事のコード例では、ButtonLinkというコンポーネント(TanStack RouterのLinkコンポーネントをラップしたもの)を使用している。このButtonLinkは、to="/sign-in"でサインインページへのパスを指定し、さらにsearch={{ redirectTo: router.state.location.href }}とすることで、現在のページの完全なURL(router.state.location.hrefがこれを示す)をredirectToという検索パラメーターとしてサインインページに渡している。この設定により、ユーザーがどのページからサインインボタンを押しても、ログイン後にその元のページに正確に戻ることが可能になる。この明示的なアプローチの利点はその高い信頼性にあるが、欠点としては、サインインページへリンクする箇所が複数ある場合、それぞれの場所でredirectToパラメーターを追加する手間がかかる点が挙げられる。ただし、これはヘルパー関数やカスタムフックで対応可能であり、通常は大きな課題とはならない。
二つ目のアプローチは、「以前の場所を自動的に取得する」方法である。これは、ユーザーがサインインページへ遷移する際に、redirectToのような検索パラメーターを明示的に渡すことなく、ルーターが自動的に直前のページを記憶し、ログイン後にそこへ戻ることを可能にする。記事では、usePreviousLocationというカスタムフックが提案されている。
このusePreviousLocationフックは、ReactのuseStateとuseEffectという基本的なフック、そしてTanStack Routerの機能を組み合わせて実装されている。useStateは、コンポーネント内で状態(データ)を保持するために使われ、ここでは以前の場所のURLを保存する。useEffectは、コンポーネントが初めて描画された時や、特定のデータが変更された時に実行される処理を定義するフックである。このフックの核心は、router.subscribe('onResolved', ...)という部分にある。これは、TanStack Routerが提供する購読機能で、ルーターがページ遷移を完了するたびに指定された処理を実行する。その処理の中では、遷移元の情報であるfromLocationが提供されるため、そのhrefプロパティ(URL)をsetPreviousLocationを使ってステートに保存する。もしfromLocationが存在しない場合(例えば、アプリケーションの初回ロード時など)は、デフォルトでトップページ(/)が設定されるようになっている。
このusePreviousLocationフックをサインインフォームで利用すると、redirectToパラメーターを明示的に渡す手間が一切なくなる。サインインフォームコンポーネントは、このフックを呼び出すだけでpreviousLocation(直前のページのURL)を取得でき、ログイン成功後にnavigate({ to: previousLocation })を使ってそのURLへリダイレクトするのである。この方法は非常にシンプルでコード量が少なくなる利点があるが、記事ではその安定性や信頼性についてはまだ実験的であると述べている点に注意が必要である。
記事では、これら二つのアプローチを組み合わせることで、より堅牢なユーザー体験を実現できると提案している。具体的には、サインインフォームがredirectToプロパティを受け取るようにしつつ、もしredirectToが提供されていない場合には、usePreviousLocationフックで取得したpreviousLocationを利用するという方法である。これは、JavaScriptのNullish Coalescing Operator (??) を使って表現される。redirectTo ?? previousLocationと書くことで、redirectToがnullまたはundefinedの場合にのみpreviousLocationが使われるようになる。これにより、開発者が特定のシナリオで明示的なリダイレクト先を指定したい場合はそれが優先され、それ以外の場合は自動的に前のページに戻るという、柔軟かつ安全なリダイレクト処理が可能となる。
まとめると、このニュース記事は、ウェブアプリケーションでユーザーがログイン後に元のページに戻れるようにするための具体的な二つの実装方法を紹介している。一つは、サインインページへのリンクに明示的に戻り先のURLを検索パラメーターとして渡す方法。もう一つは、ルーターのイベントを購読して自動的に直前のページを記憶する方法である。どちらのアプローチも、ユーザーがログインによって現在の作業状況を失うことなく、スムーズにアプリケーションを利用できるようにするための重要なテクニックであり、これらの知識はシステムエンジニアとしてユーザーフレンドリーなウェブサービスを開発する上で非常に役立つ。