当前位置: 首页 > news >正文

useRouteLeaveConfirm 路由离开确认弹窗 Hook

组件说明:

useRouteLeaveConfirm 是一个自定义 React Hook,用于在页面有未保存内容时,阻止路由切换并弹出确认弹窗。支持自定义弹窗内容和按钮,适用于表单编辑等场景。

代码实现:

## 代码实现import { useEffect, useRef } from 'react';
import { useBlocker } from 'react-router-dom';
import { Modal, Button } from 'antd';export function useRouteLeaveConfirm({when,message = '当前页面有未保存的内容,确定要离开吗?',title = '离开确认',onOk,onCancel,confirmConfig = {},
}) {const modalRef = useRef(null);const blocker = useBlocker(() => when);useEffect(() => {if (blocker && blocker.state === 'blocked') {if (modalRef.current) {modalRef.current.destroy();modalRef.current = null;}const handleClose = () => {if (modalRef.current) {modalRef.current.destroy();modalRef.current = null;}};// 从 confirmConfig 中解构出 buttons,其余的 props 依然传递给 Modalconst { buttons, ...restConfig } = confirmConfig;const modalProps = {title,content: message,keyboard: false,...restConfig,};// 如果传入了自定义 buttons,则使用 footer 来自定义按钮if (buttons && buttons.length > 0) {modalProps.footer = (<div style={{ textAlign: 'right' }}>{buttons.map((button, index) => (<ButtonclassName='ml-2'key={index}{...button.props}onClick={async () => {let shouldClose = true;if (button.onClick) {// 允许 onClick 返回 false 来阻止弹窗关闭const result = await Promise.resolve(button.onClick());if (result === false) {shouldClose = false;}}if (button.action === 'proceed') {blocker.proceed?.();} else if (button.action === 'reset') {blocker.reset?.();}if (shouldClose) {handleClose();}}}>{button.text}</Button>))}</div>);} else {// 否则,使用默认的 onOk 和 onCancelmodalProps.okText = confirmConfig.okText || '确定';modalProps.cancelText = confirmConfig.cancelText || '取消';modalProps.onOk = async () => {try {await onOk?.();} finally {blocker.proceed?.();handleClose();}};modalProps.onCancel = () => {onCancel?.();blocker.reset?.();handleClose();};}modalRef.current = Modal.confirm(modalProps);}if (!when && modalRef.current) {modalRef.current.destroy();modalRef.current = null;}}, [blocker, when, title, message, onOk, onCancel, confirmConfig]);useEffect(() => {return () => {if (modalRef.current) {modalRef.current.destroy();}};}, []);
}
```## API| 参数         | 类型      | 说明                                   |
| ------------ | --------- | -------------------------------------- |
| when         | boolean   | 是否阻止路由切换并弹窗                 |
| title        | string    | 弹窗标题                               |
| message      | string    | 弹窗内容                               |
| onOk         | function  | 点击“确定”时回调                       |
| onCancel     | function  | 点击“取消”时回调                       |
| confirmConfig| object    | 弹窗配置,支持自定义按钮、内容等        |### confirmConfig.buttons
- `text`:按钮文本
- `action`:'proceed'(继续切换)、'reset'(取消切换)
- `props`:Antd Button 额外属性
- `onClick`:按钮点击回调,返回 `false` 可阻止弹窗关闭

用法示例:

###使用示例```jsx
import { useRouteLeaveConfirm } from '@/hooks/useRouteLeaveConfirm';const confirmConfig = useMemo(() => ({buttons: [{ text: '取消', action: 'reset' },{ text: '不保存', action: 'proceed' },{ text: '保存', props: { type: 'primary' },action: 'proceed', onClick: handleSave },],
}), [handleSave]);useRouteLeaveConfirm({when: isDirty,title: '您有未保存的更改',message: '您想在离开前保存吗?',confirmConfig,
});
```isDirty 这个值用于标记当前页面内容是否被修改但尚未保存。 true 弹框弹出 如果前后数据一致,没有发生什么变化则为false
action: 'proceed' //这个是用来控制执行完事件后是否要跳转页面## 注意事项
- 当我们执行的保存逻辑是异步函数时,记得加上async/awiat
- 依赖 react-router-dom v6 的 `useBlocker`。
- 弹窗会在路由切换被阻止时自动弹出,无需手动调用。
- 支持自定义按钮和回调,满足复杂交互需求。

http://www.lryc.cn/news/604402.html

相关文章:

  • ECCV | 2024 | LocalMamba:具有窗口选择性扫描的视觉状态空间模型
  • 2019 年 NOI 最后一题题解
  • C语言数据结构(1)顺序表专题2.顺序表的应用
  • Mac下的Homebrew
  • Python 中使用 OpenCV 库来捕获摄像头视频流并在窗口中显示
  • 深入理解 Doris Compaction:提升查询性能的幕后功臣
  • webpack-性能优化
  • 破茧 JDBC:MyBatis 在 Spring Boot 中的轻量实践录
  • 2025年6月电子学会青少年软件编程(C语言)等级考试试卷(二级)
  • C++ 中 NULL 与 nullptr 有什么区别?
  • RAG实战指南 Day 29:RAG系统成本控制与规模化
  • WebRTC核心组件技术解析:架构、作用与协同机制
  • mangoDB面试题及详细答案 117道(071-095)
  • Python深度挖掘:openpyxl与pandas高效数据处理实战指南
  • APM32芯得 EP.27 | 告别IDE,为APM32F411打造轻量级命令行开发工作流
  • 微服务消息队列之——RabbitMQ
  • .NET 10 中的新增功能系列文章2——ASP.NET Core 中的新增功能
  • PostGIS安装与pg_dump/pg_restore排错
  • flutter 记录一个奇怪的问题
  • 在 Mac 上用 Vagrant 安装 K8s
  • InfluxDB 3 数据库命名与创建全攻略:规范、限制与实战指南
  • 《零基础入门AI:传统机器学习核心算法解析(KNN、模型调优与朴素贝叶斯)》
  • GaussDB 数据库架构师(十二) 数据库对象修改审计设置
  • Redis学习------缓存穿透
  • llama factory本地部署常见问题
  • Git版本控制器
  • 人工智能与家庭:智能家居的便捷与隐患
  • gdb调试的限制和配置自动生成core
  • 2023 年 NOI 最后一题题解
  • 【C++篇】哈希扩展:位图和布隆过滤器+哈希切割