import { useCallback, useState, useContext, useEffect } from "react";
import { useNavigate, UNSAFE_NavigationContext } from "react-router-dom";
export const useTest = (
? when: boolean,
? onSuccess: () => void
): {
? navigationWasBlocked: boolean;
? handleCancel: () => void;
? handleOk: () => void;
} => {
? const [nextLocation, setNextLocation] = useState(null);
? const { navigator } = useContext(UNSAFE_NavigationContext);
? const navigate = useNavigate();
? console.log("setNextLocation outer ", nextLocation);
? const handleCancel = () => {
? ? //點(diǎn)擊取消按鈕調(diào)用此方法,清空當(dāng)前要跳轉(zhuǎn)到的鏈接
? ? setNextLocation(undefined);
? };
? const handleOk = () => {
? ? //點(diǎn)擊了同意按鈕
? ? debugger;
? ? onSuccess(); //先調(diào)用回調(diào)函數(shù)堆生,此函數(shù)在調(diào)用此hook時(shí)傳入
? ? setNextLocation(undefined); //跳轉(zhuǎn)完畢后清空竹祷,因?yàn)閟etState的異步性沾谓,放這里和放最后一樣
? ? navigate(nextLocation); //跳轉(zhuǎn)到當(dāng)前需要跳轉(zhuǎn)的鏈接,雖然上面設(shè)置了undefind但是由于異步性這里獲取的還是未清空時(shí)的鏈接
? };
? const blocker: any = useCallback(
? ? ({ action, location: nextLocation, retry }) => {
? ? ? console.log("location ", location);
? ? ? debugger;
? ? ? switch (action) {
? ? ? ? case "REPLACE": {
? ? ? ? ? retry();
? ? ? ? ? return;
? ? ? ? }
? ? ? ? case "POP":
? ? ? ? case "PUSH": {
? ? ? ? ? //POP:點(diǎn)擊瀏覽器后退按鈕
? ? ? ? ? //PUSH: 點(diǎn)擊了某個(gè)按鈕跳轉(zhuǎn)頁面
? ? ? ? ? setNextLocation(nextLocation); //無論是哪種蕊温,都把當(dāng)前要跳轉(zhuǎn)到的鏈接信息放入currentLocation
? ? ? ? ? return;
? ? ? ? }
? ? ? ? default:
? ? ? ? ? break;
? ? ? }
? ? },
? ? []
? );
? //調(diào)用此hook
? // const { navigationWasBlocked, handleCancel, handleOk } = useTest(true, () => {
? // ? ?console.log('called');
? // });
? useEffect(() => {
? ? if (!when) return; //當(dāng)when為false時(shí)表示不需要啟用此功能
? ? if (nextLocation) return; //如果NextLocation存在值就跳出
? ? if (!("block" in navigator)) return; //block屬性不存在就跳出脉顿,瀏覽器兼容?
? ? const unblock = (navigator as any).block((tx: any) => {
? ? ? debugger;
? ? ? console.log("tttttttttt ? ?", tx.retry.toString());
? ? ? //監(jiān)聽路由變化莉恼,每當(dāng)點(diǎn)擊跳轉(zhuǎn)按鈕會(huì)調(diào)用此函數(shù)
? ? ? //這個(gè)函數(shù)會(huì)傳入tx,形如:
? ? ? // {
? ? ? // ? ? "action": "PUSH",
? ? ? // ? ? "location": {
? ? ? // ? ? ? ? "pathname": "/dummy-test-01",
? ? ? // ? ? ? ? "hash": "",
? ? ? // ? ? ? ? "search": "",
? ? ? // ? ? ? ? "state": null,
? ? ? // ? ? ? ? "key": "igdvd1g0"
? ? ? // ? ? }
? ? ? // ? ? "retry":function(){go(delta * -1);}
? ? ? // }
? ? // ? debugger;
? ? // ? if (tx.action === "POP") {
? ? // ? ? tx.action = "REPLACE";
? ? // ? }
? ? ? const autoUnblockingTx = {
? ? ? ? ...tx,
? ? ? ? retry() {
? ? ? ? ? //擴(kuò)展retry方法
? ? ? ? ? //如果Replace的情況就會(huì)走到這里
? ? ? ? ? //第一步把綁定的監(jiān)聽事件移除
? ? ? ? ? unblock();
? ? ? ? ? //接著調(diào)tx上的retry方法
? ? ? ? ? //go(delta * -1) 比如點(diǎn)擊后退delta為1,變成go(-1)俐银,改變url
? ? ? ? ? tx.retry();
? ? ? ? },
? ? ? };
? ? ? blocker(autoUnblockingTx); //調(diào)用blocker函數(shù)(設(shè)置當(dāng)前router信息)
? ? });
? ? console.log("unblock ", unblock);
? ? return unblock; //返回block函數(shù)的調(diào)用結(jié)果(是一個(gè)function組件卸載時(shí)調(diào)用此function)移除beforeunload listener
? }, [navigator, blocker, when, nextLocation]);
? return {
? ? navigationWasBlocked: Boolean(nextLocation),
? ? handleCancel,
? ? handleOk,
? };
};