For AI agents: the complete documentation index is available at /toi/ja/llms.txt, the full documentation bundle is available at /toi/ja/llms-full.txt, and this page is available as Markdown at /toi/ja/guide/basic/navigation.md.
  • 日本語
  • ページ遷移で閉じる

    別のページへ遷移しても、未回答のリクエストが自動的に確定することはありません。toi がレンダリングするコンポーネントは ToiHost の中にあり、ToiHost は通常ルーティングの対象外の場所に置かれるため(ホストのマウントを参照)、ページ遷移をまたいでもマウントされたままになります。あるページで開いた確認ダイアログは、ユーザーが次のページへ移動した後もそこに残ります。

    それが望ましいかどうかはコンポーネント次第です。保存完了を知らせるトーストであれば、表示のきっかけになったページより長く生き残っても問題ないでしょう。一方、前のページの内容に紐づいた確認ダイアログは残っていては困るのが普通で、reject() を呼び出して閉じるべきです。これは解決するで説明した「リクエストが放棄された」ケースにあたります。

    ユーザーがページを離れたときにコンポーネントを閉じたい場合は、Navigation API の currententrychange イベントを監視してください。現在の履歴エントリが変わった後に発火するイベントなので、そこから reject() を呼び出します。

    import { useEffect } from 'react';
    
    import type { ToiProps } from '@praha/toi';
    import type { FC } from 'react';
    
    const Confirm: FC<ToiProps<boolean>> = ({ ref, resolve, reject }) => {
      useEffect(() => {
        const abandon = () => reject();
        navigation.addEventListener('currententrychange', abandon);
        return () => navigation.removeEventListener('currententrychange', abandon);
      }, [reject]);
    
      return (
        <dialog ref={ref} open>
          <button onClick={() => resolve(true)}>OK</button>
          <button onClick={() => resolve(false)}>Cancel</button>
        </dialog>
      );
    };

    @praha/react-kit の useNavigationEventListener フックを使うと、これをより簡潔に書けます。コンポーネントのライフタイムにわたって購読し、再購読なしに常に最新の listener を呼び出します。

    import { useNavigationEventListener } from '@praha/react-kit';
    
    import type { ToiProps } from '@praha/toi';
    import type { FC } from 'react';
    
    const Confirm: FC<ToiProps<boolean>> = ({ ref, resolve, reject }) => {
      useNavigationEventListener({
        type: 'currententrychange',
        listener: () => reject(),
      });
    
      return (
        <dialog ref={ref} open>
          <button onClick={() => resolve(true)}>OK</button>
          <button onClick={() => resolve(false)}>Cancel</button>
        </dialog>
      );
    };