使用 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 与自定义逻辑相结合,您可以构建优先考虑安全性和可用性的强大用户体验。