React Router v.6 usePrompt TypeScript

idk*_*gon 6 reactjs react-router react-router-dom

我基本上是想拦截路线变化。也许React Router v6beforeEach中类似于 vue 的东西可能有用,因为 React Router v.6包含.usePrompt

在每次路线更改之前,我想做一些逻辑 - 该逻辑可能需要中断甚至根据结果更改最终路线。

我已经四处寻找,但我真的找不到解决这个特定问题的东西。

提前致谢。

idk*_*gon 16

usePrompt目前他们已经从react-router v6中删除了。

我从ui.dev找到了一个解决方案并添加了 TypeScript 支持,现在正在使用它,直到反应路由器将带回usePrompt/useBlocker钩子

import { History, Transition } from 'history';
import { useCallback, useContext, useEffect } from "react";
import { Navigator } from 'react-router';
import { UNSAFE_NavigationContext as NavigationContext } from "react-router-dom";

type ExtendNavigator = Navigator & Pick<History, "block">;
export function useBlocker(blocker: (tx: Transition) => void, when = true) {
    const { navigator } = useContext(NavigationContext);

    useEffect(() => {
        if (!when) return;

        const unblock = (navigator as ExtendNavigator).block((tx) => {
            const autoUnblockingTx = {
                ...tx,
                retry() {
                    unblock();
                    tx.retry();
                },
            };

            blocker(autoUnblockingTx);
        });

        return unblock;
    }, [navigator, blocker, when]);
}

export default function usePrompt(message: string, when = true) {
    const blocker = useCallback((tx: Transition) => {
        if (window.confirm(message)) tx.retry();
    }, [message]);

    useBlocker(blocker, when);
}
Run Code Online (Sandbox Code Playgroud)

然后可以在任何视图/组件中使用它,当条件为真时,您希望显示“您确定要离开吗?”消息。

usePrompt("Do you want to leave?", isFormDirty());
Run Code Online (Sandbox Code Playgroud)