LoginSignup
0
0

react-router-dom v6で入力した情報を破棄するかどうかの確認ダイアログを表示する方法

Posted at

実現したいこと

ユーザーがフォーム等に値を入力後、
・ページをリロードしようとした時に確認ダイアログを表示する。
Screenshot 2023-10-29 at 13.34.06.png
・他のページに遷移しようとした時に確認ダイアログを表示する。
Screenshot 2023-10-29 at 13.34.17.png

課題

react-router-dom v6ではページ離脱を防ぐために必要なuseBlockerが削除されていて、別途実装が必要。

参考
https://qiita.com/yukiji/items/89d5174f13cdc21a622f#%E3%83%AA%E3%83%B3%E3%82%AF%E3%81%A7%E3%81%AE%E9%81%B7%E7%A7%BB%E6%88%BB%E3%82%8B%E9%80%B2%E3%82%80

使用したライブラリ

react-router-prompt
https://github.com/sshyam-gupta/react-router-prompt/tree/main

実際は、このライブラリの中で必要な3つのファイルのみをコピーして使いました。
https://github.com/sshyam-gupta/react-router-prompt/blob/main/src/hooks/use-confirm.ts
https://github.com/sshyam-gupta/react-router-prompt/blob/main/src/hooks/use-prompt.ts
https://github.com/sshyam-gupta/react-router-prompt/blob/main/src/index.tsx

理由としては、react-routerの非公式のライブラリで今後も継続的にアップデートされるかが分からなかったのと、上記3つのファイルのみ移植するだけで使えそうだったので、今回はライブラリをそのまま使うのではなく、コードを移植して使いました。

こちらが自作したコードのリポジトリです。
https://github.com/nobu0605/react-router-prompt

もちろん、ライブラリをそのまま使うことも可能です。

使い方

ライブラリを使った場合も自作の場合も同じで以下のようにReactRouterPromptを呼び出して、ダイアログなどをラップして使っています。
when propsに変更検知のflagを渡します。

/components/UnsavedConfirmDialog.tsx
import ReactRouterPrompt from "./ReactRouterPrompt";
import Button from "@mui/material/Button";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import DialogContentText from "@mui/material/DialogContentText";
import DialogTitle from "@mui/material/DialogTitle";

type Props = {
  when: boolean;
};

export function UnsavedConfirmDialog({ when }: Props) {
  return (
    <ReactRouterPrompt when={when}>
      {({ isActive, onConfirm, onCancel }) =>
        isActive && (
          <Dialog open={isActive}>
            <DialogTitle>Do you really want to leave?</DialogTitle>
            <DialogContent>
              <DialogContentText>
                Your changes will not be saved.
              </DialogContentText>
            </DialogContent>
            <DialogActions>
              <Button onClick={onCancel}>cancell</Button>
              <Button onClick={onConfirm} autoFocus>
                ok
              </Button>
            </DialogActions>
          </Dialog>
        )
      }
    </ReactRouterPrompt>
  );
}


補足

ページをリロードしようとした時に確認ダイアログを表示する場合に、beforeunloadイベントを使うのですが、カスタムメッセージや自作のダイアログは表示できないみたいです。
各ブラウザの既定のダイアログが表示されます。
https://qiita.com/nantekkotai/items/9a6e2c98ed704934ab47

0
0
0

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