使用 useCallbackPrompt 和 useBlocker 掌握 React 中的导航控制
在现代网络应用中,打造无缝导航体验至关重要。无论您是保护未保存的更改还是确认关键操作,控制导航流程都能确保更好的用户体验。
本文介绍了**useCallbackPrompt**,一个基于**useBlocker**构建的自定义 React hook,它通过可自定义的提示提供对导航事件的增强控制。

什么是 useCallbackPrompt?
`useCallbackPrompt` 是一个自定义钩子,旨在拦截导航事件并在允许用户离开之前显示确认提示。它使用较低级别的 **useBlocker** 钩子构建,该钩子与 React Router 的内部导航 API 集成。
什么是 useBlocker?
`useBlocker` 是一个实用钩子,它通过监听 React Router 的导航事件来提供核心阻止机制。它允许在尝试导航时创建自定义逻辑。
以下是 useBlocker 的代码:
import { useContext, useEffect } from 'react';
import { UNSAFE_NavigationContext } from 'react-router-dom';
const useBlocker = (blocker, enable = true) => {
const navigator = useContext(UNSAFE_NavigationContext).navigator;
useEffect(() => {
if (!enable) return;
const unblock = navigator.block((tx) => {
const autoUnblockingTx = {
...tx,
retry() {
unblock();
tx.retry();
},
};
blocker(autoUnblockingTx);
});
return unblock;
}, [navigator, blocker, enable]);
};
export default useBlocker;useCallbackPrompt 的工作原理
`useCallbackPrompt` 扩展了 `useBlocker`,为管理导航提示提供了更加用户友好的界面。
实现如下:
import { useCallback, useEffect, useState } from 'react';
import { useLocation, useNavigate } from 'react-router';
import useBlocker from './useBlocker';
const useCallbackPrompt = (enable) => {
const navigate = useNavigate();
const location = useLocation();
const [showPrompt, setShowPrompt] = useState(false);
const [lastLocation, setLastLocation] = useState(null);
const [confirmedNavigation, setConfirmedNavigation] = useState(false);
// Cancel the navigation
const cancelNavigation = useCallback(() => {
setShowPrompt(false);
}, []);
// Block navigation and show prompt
const handleBlockedNavigation = useCallback(
(nextLocation) => {
if (
!confirmedNavigation &&
nextLocation?.location?.pathname !== location?.pathname
) {
setShowPrompt(true);
setLastLocation(nextLocation);
return false;
}
return true;
},
[confirmedNavigation, location]
);
// Confirm the navigation
const confirmNavigation = useCallback(() => {
setShowPrompt(false);
setConfirmedNavigation(true);
}, []);
useEffect(() => {
if (confirmedNavigation && lastLocation) {
navigate(lastLocation.location.pathname);
setConfirmedNavigation(false);
}
}, [confirmedNavigation, lastLocation, navigate]);
useBlocker(handleBlockedNavigation, enable);
return [showPrompt, confirmNavigation, cancelNavigation];
};
export default useCallbackPrompt;使用 useCallbackPrompt 的优点
如何使用 useCallbackPrompt
以下是如何在 React 应用中使用 `useCallbackPrompt` 的方法:
1.安装 React Router
确保 React Router 已安装:
npm install react-router-dom
2. 使用钩子
以下是一个表单示例,当用户离开且未保存更改时会显示提示:
import React, { useState } from 'react';
import useCallbackPrompt from './useCallbackPrompt';
const FormPage = () => {
const [isDirty, setIsDirty] = useState(false);
const [showPrompt, confirmNavigation, cancelNavigation] = useCallbackPrompt(isDirty);
return (
<>
{showPrompt && (
You have unsaved changes. Do you really want to leave?
3. 自定义模态框
您可以使用自己最喜欢的 UI 库(例如,Material-UI、TailwindCSS)中的设计替换模态框。
使用案例
结论
`useCallbackPrompt` 和 `useBlocker` 是管理 React 应用程序中导航的宝贵工具。通过将 React Router 的导航 API 与自定义逻辑相结合,您可以构建优先考虑安全性和可用性的强大用户体验。