React中如何结合路由使用Modal实现列表项查看编辑及删除确认弹窗
React 结合路由实现 Modal 弹窗操作方案
实现思路
你需要的两个功能可以分别按以下逻辑实现,其中查看弹窗支持和路由绑定,删除确认弹窗用内部状态控制即可:
- 删除确认:点击删除按钮后先打开确认弹窗,用户点击确认后再执行删除接口调用
- 查看弹窗:支持两种实现方式,可根据业务需要选择:
- 路由绑定模式:打开弹窗时URL同步更新,刷新后弹窗仍保持打开,支持直接分享URL打开对应详情弹窗
- 内部状态模式:URL无变化,纯组件内状态控制弹窗显隐,实现成本更低
前置准备
- 确保已安装
react-router-dom(推荐v6+版本) - 你可以使用任意UI库的Modal组件(比如Ant Design的Modal、React Bootstrap的Modal),以下示例用通用结构编写,可直接替换为你项目中用的组件
- 你原有代码中接口返回值存在
holidays状态,但渲染用的是res状态,缺少setRes逻辑,以下代码会先修复这个问题
完整改造代码(路由绑定模式)
第一步:调整路由配置
// 你的路由配置文件中,新增带可选参数的路由,指向同一个列表组件 { path: '/holiday', element: <AddHolidayForm />, children: [ // 可选参数id,匹配查看弹窗的路由 { path: 'view/:id', element: <AddHolidayForm /> } ] }
第二步:改造组件代码
import { useState, useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import axios from 'axios'; // 引入你用的Modal组件,这里以React Bootstrap为例,可替换为其他UI库的Modal import { Modal, Button, Table } from 'react-bootstrap'; import { FaEye, FaTrashAlt } from 'react-icons/fa'; const AddHolidayForm = () => { // 路由相关API const { id: viewId } = useParams(); const navigate = useNavigate(); // 原有业务状态 const [holidays, setHolidays] = useState([]); const [page, setPage] = useState(0); // 补全你原有分页参数 const [rowsPerPage, setRowsPerPage] = useState(10); // 补全你原有分页参数 // 弹窗相关状态 const [delModalVisible, setDelModalVisible] = useState(false); const [currentDelId, setCurrentDelId] = useState(null); // 当前查看的节假日详情 const [currentViewHoliday, setCurrentViewHoliday] = useState(null); useEffect(() => { loadHoliday(); }, []); // 路由参数变化时,自动打开/关闭查看弹窗 useEffect(() => { if (viewId && holidays.length) { // 从列表中找到对应id的节假日信息,也可以单独调接口查详情 const holiday = holidays.find(item => item.id === Number(viewId)); setCurrentViewHoliday(holiday || null); } else { setCurrentViewHoliday(null); } }, [viewId, holidays]); const loadHoliday = async () => { const res = await axios.post(`http://localhost:.....`, {}); const list = res.data.reverse(); setHolidays(list); // 修复你原有代码漏写的setRes,这里直接用holidays渲染也可以,不需要多余的res状态 // setRes(list); }; const deleteHoliday = async () => { await axios.delete(`http://..../${currentDelId}`); // 关闭删除弹窗 setDelModalVisible(false); setCurrentDelId(null); loadHoliday(); }; return ( <div className="container"> <div className="py-4"> <Table responsive> <thead className="thead-dark"> <tr> <th scope="col">#</th> <th>Action</th> <th scope="col">Name</th> <th scope="col">Start Time</th> <th scope="col">End Time</th> </tr> </thead> <tbody> {holidays.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) .map((holiday, index) => { return ( <tr key={holiday.id}> <th scope="row">{index + 1}</th> <td> <Button className="btn btn-primary mr-2" onClick={() => navigate(`/holiday/view/${holiday.id}`)} > <FaEye /> </Button> <Button className="btn btn-danger" onClick={() => { setCurrentDelId(holiday.id); setDelModalVisible(true); }} > <FaTrashAlt /> </Button> </td> <td>{holiday.name}</td> <td>{holiday.startTime}</td> <td>{holiday.endTime}</td> </tr> ) }) } </tbody> </Table> </div> {/* 删除确认弹窗 */} <Modal show={delModalVisible} onHide={() => setDelModalVisible(false)}> <Modal.Header closeButton> <Modal.Title>确认删除</Modal.Title> </Modal.Header> <Modal.Body>确定要删除这个节假日吗?删除后无法恢复。</Modal.Body> <Modal.Footer> <Button variant="secondary" onClick={() => setDelModalVisible(false)}> 取消 </Button> <Button variant="danger" onClick={deleteHoliday}> 确认删除 </Button> </Modal.Footer> </Modal> {/* 查看详情弹窗 */} <Modal show={!!currentViewHoliday} onHide={() => navigate('/holiday')}> <Modal.Header closeButton> <Modal.Title>节假日详情</Modal.Title> </Modal.Header> <Modal.Body> {currentViewHoliday && ( <div> <p>名称:{currentViewHoliday.name}</p> <p>开始时间:{currentViewHoliday.startTime}</p> <p>结束时间:{currentViewHoliday.endTime}</p> {/* 可以加更多详情字段,或者引入编辑表单组件 */} </div> )} </Modal.Body> <Modal.Footer> <Button variant="secondary" onClick={() => navigate('/holiday')}> 关闭 </Button> </Modal.Footer> </Modal> </div> ); } export default AddHolidayForm;
关键逻辑说明
- 如果你不需要路由绑定,只需要把查看弹窗的显隐用单独的state比如
viewModalVisible控制即可,点击查看按钮时直接给currentViewHoliday赋值并打开弹窗,不需要调用navigate也不需要调整路由配置 - 如果详情数据需要单独拉取接口,可以在检测到
viewId变化的时候调用详情接口,不需要从现有列表里取 - 如果要加编辑功能,只需要在查看弹窗里加编辑按钮,或者单独做一个编辑弹窗,逻辑和查看弹窗一致
内容的提问来源于stack exchange,提问作者efnan
相关产品推荐
相关产品推荐

