点击MUI X Data Grid行内按钮触发MUI Modal的实现方案
在MUI X Data Grid行内按钮点击时打开MUI Modal的实现方案
我已经实现了带有操作按钮的MUI X Data Grid组件,现在需要实现点击每行的Delete按钮时,弹出包含该行详情的MUI Modal,并且在Modal中添加按钮向服务器发送删除请求。现有DataGrid组件和Modal组件代码如下:
原UserDataGrid组件代码
function UserDataGrid() { const { allUsers, filteredUsers, setFilteredUsers, traffics } = useContext(UserContext); const handleEvent = (e) => { console.log(e.field); }; const columns = [ { field: "id", headerName: "ای دی" }, { field: "username", headerName: "یوزر" }, { field: "enable", headerName: "وضعیت", type: "boolean", width: 140, editable: true, renderCell: (params) => { return params.value ? <p>فعال</p> : <p>غیر فعال</p>; }, }, { field: "startdate", headerName: "تاریخ شروع", headerAlign: "center" }, { field: "finishdate", headerName: "تاریخ پایان" }, { field: "mobile", headerName: "موبایل" }, { field: "referral", headerName: "معرف" }, { field: "traffic", headerName: "ترافیک" }, { field: "action", headerName: "Action", width: 180, sortable: false, disableClickEventBubbling: true, renderCell: (params) => { const onClick = (e) => { const currentRow = params.row; return alert(JSON.stringify(currentRow, null, 4)); }; return ( <div direction="row" spacing={2}> <Button onClick={onClick}>Delete</Button> <Button onClick={onClick}>Edit</Button> </div> ); }, }, ]; return ( <div> <DataGrid rows={allUsers} columns={columns} loading={!allUsers.length} onCellClick={handleEvent} /> </div> ); } export default UserDataGrid;
原DeleteModal组件代码
export default function DeleteModal() { const [open, setOpen] = React.useState(false); const handleOpen = () => setOpen(true); const handleClose = () => setOpen(false); return ( <div> <Button onClick={handleOpen}>Open modal</Button> <Modal open={open} onClose={handleClose} aria-labelledby="modal-modal-title" aria-describedby="modal-modal-description" > <Box sx={style}> <Typography id="modal-modal-title" variant="h6" component="h2"> Text in a modal </Typography> <Typography id="modal-modal-description" sx={{ mt: 2 }}> Duis mollis, est non commodo luctus, nisi erat porttitor ligula. </Typography> </Box> </Modal> </div> ); }
实现步骤
- 状态提升:把Modal的
open状态和控制函数移到UserDataGrid组件中,同时新增状态存储当前点击的行数据,实现行内按钮对Modal的控制和数据传递。 - 改造Modal组件:让
DeleteModal接收open、handleClose、currentRow、handleDelete四个props,成为受控组件,专注于渲染内容和触发删除逻辑。 - 修改行内按钮事件:在DataGrid的action列中,给Delete按钮绑定打开Modal的事件,传入当前行数据。
- 添加请求逻辑:在Modal中添加确认删除按钮,调用接口完成删除操作。
修改后的完整代码
DeleteModal组件
import React from 'react'; import { Modal, Box, Typography, Button } from '@mui/material'; const style = { position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', width: 400, bgcolor: 'background.paper', border: '2px solid #000', boxShadow: 24, p: 4, }; export default function DeleteModal({ open, handleClose, currentRow, handleDelete }) { if (!currentRow) return null; return ( <Modal open={open} onClose={handleClose} aria-labelledby="modal-modal-title" aria-describedby="modal-modal-description" > <Box sx={style}> <Typography id="modal-modal-title" variant="h6" component="h2"> 删除用户确认 </Typography> <Typography id="modal-modal-description" sx={{ mt: 2 }}> 确定要删除用户 <strong>{currentRow.username}</strong> 吗? </Typography> <Typography sx={{ mt: 2 }}> 用户ID: {currentRow.id} <br /> 手机号: {currentRow.mobile} </Typography> <Box sx={{ mt: 3, display: 'flex', justifyContent: 'flex-end', gap: 2 }}> <Button onClick={handleClose}>取消</Button> <Button variant="contained" color="error" onClick={() => handleDelete(currentRow.id)}> 确认删除 </Button> </Box> </Box> </Modal> ); }
UserDataGrid组件
import React, { useState } from 'react'; import { DataGrid, Button } from '@mui/x-data-grid'; import { useContext } from 'react'; import UserContext from './UserContext'; // 请根据实际路径调整 import DeleteModal from './DeleteModal'; // 请根据实际路径调整 function UserDataGrid() { const { allUsers } = useContext(UserContext); const [modalOpen, setModalOpen] = useState(false); const [currentRowData, setCurrentRowData] = useState(null); // 替换为实际的删除接口调用逻辑 const handleDeleteUser = async (userId) => { try { // 示例接口请求:await fetch(`/api/users/${userId}`, { method: 'DELETE' }); console.log(`删除用户ID: ${userId}`); // 删除成功后可更新表格数据,例如从allUsers中移除对应行 handleCloseModal(); } catch (error) { console.error('删除失败:', error); } }; const handleOpenModal = (row) => { setCurrentRowData(row); setModalOpen(true); }; const handleCloseModal = () => { setModalOpen(false); setCurrentRowData(null); }; const columns = [ { field: "id", headerName: "ای دی" }, { field: "username", headerName: "یوزر" }, { field: "enable", headerName: "وضعیت", type: "boolean", width: 140, editable: true, renderCell: (params) => { return params.value ? <p>فعال</p> : <p>غیر فعال</p>; }, }, { field: "startdate", headerName: "تاریخ شروع", headerAlign: "center" }, { field: "finishdate", headerName: "تاریخ پایان" }, { field: "mobile", headerName: "موبایل" }, { field: "referral", headerName: "معرف" }, { field: "traffic", headerName: "ترافیک" }, { field: "action", headerName: "Action", width: 180, sortable: false, disableClickEventBubbling: true, renderCell: (params) => { return ( <div style={{ display: 'flex', gap: 10 }}> <Button variant="contained" color="error" onClick={() => handleOpenModal(params.row)} > Delete </Button> <Button variant="outlined">Edit</Button> </div> ); }, }, ]; return ( <div> <DataGrid rows={allUsers} columns={columns} loading={!allUsers.length} /> <DeleteModal open={modalOpen} handleClose={handleCloseModal} currentRow={currentRowData} handleDelete={handleDeleteUser} /> </div> ); } export default UserDataGrid;
关键说明
- 状态提升后,
UserDataGrid完全控制Modal的显示状态和当前行数据,避免组件间状态不同步问题。 DeleteModal作为受控组件,只负责渲染内容和触发删除回调,逻辑解耦更清晰。- 行内按钮通过
handleOpenModal直接传递当前行数据,确保Modal能展示正确的用户详情。 handleDeleteUser函数可替换为实际的API请求,完成后关闭Modal并更新表格数据。
内容的提问来源于stack exchange,提问作者rasool bagheri
相关产品推荐
相关产品推荐

