You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MUI DataGrid选中行后按钮禁用状态不生效问题排查

MUI DataGrid选中行后按钮禁用状态不更新的解决方案

问题根源

  • 两个DataGrid(Contacts和Leads)共用同一个selectedRow状态,选中行操作会互相干扰,导致按钮状态逻辑混乱
  • Lead表格未绑定onSelectionModelChange事件,选中Lead行时不会触发状态更新
  • Edit Lead按钮复用了Contact的编辑逻辑,路由跳转逻辑不匹配

修复方案

  1. 为Contacts和Leads分别维护独立的选中状态:selectedContacts和selectedLeads
  2. 给Lead的DataGrid绑定对应的选中事件处理函数
  3. 为Lead编写独立的编辑、删除点击处理函数

修复后的完整代码

import * as React from 'react';
import { useEffect, useState } from "react";
import axios from 'axios';
import AddIcon from '@mui/icons-material/Add';
import EditIcon from '@mui/icons-material/Edit';
import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline';
import FormatListNumberedRtlOutlinedIcon from '@mui/icons-material/FormatListNumberedRtlOutlined';
import { DataGrid } from '@mui/x-data-grid';
import { Container, Box, Typography, Button, Stack } from '@mui/material';
import { Link, useNavigate } from "react-router-dom";
import MyAppBar from "../components/MyAppBar";
import '../styles/init.css';

const Dashboard = () => {
    const [contacts, setContacts] = useState([]);
    const [leads, setLeads] = useState([]);
    // 为Contacts和Leads分别维护选中状态
    const [selectedContacts, setSelectedContacts] = useState([]);
    const [selectedLeads, setSelectedLeads] = useState([]);
    const navigate = useNavigate();

    useEffect(() => {
        const fetchAllContacts = async () => {
            try {
                const res = await axios.get('http://localhost:3000/data/contacts');
                setContacts(res.data);
            } catch (err) {
                console.log(err);
            }
        };

        const fetchAllLeads = async () => {
            try {
                const res = await axios.get('http://localhost:3000/data/leads');
                setLeads(res.data);
            } catch (err) {
                console.log(err);
            }
        };

        fetchAllContacts();
        fetchAllLeads();
    }, []);

    const contactColumns = [
        { field: 'id', headerName: 'ID', width: 70 },
        { field: 'person', headerName: 'Nama', width: 150, editable: true },
        { field: 'person_address', headerName: 'Alamat', width: 150, editable: true },
        { field: 'status', headerName: 'Status', width: 100, editable: true },
        { field: 'descriptions', headerName: 'Deskripsi', width: 200, editable: true },
    ];

    const leadColumns = [
        { field: 'id', headerName: 'ID', width: 70 },
        { field: 'invoice_date', headerName: 'Invoice', width: 130, editable: true },
        { field: 'sales_name', headerName: 'Nama Sales', width: 150, editable: true },
        { field: 'person', headerName: 'Pelanggan', width: 150 },
        { field: 'descriptions', headerName: 'Deskripsi', width: 200, editable: true },
        { field: 'lead_status', headerName: 'Status Lead', width: 150, editable: true },
        { field: 'notes', headerName: 'Catatan', width: 200, editable: true },
        { field: 'deal_date', headerName: 'Tanggal Deal', width: 150, editable: true },
    ];

    // Contacts选中事件处理
    const handleContactSelectionChange = (newSelection) => {
        setSelectedContacts(newSelection);
    };

    // Leads选中事件处理
    const handleLeadSelectionChange = (newSelection) => {
        setSelectedLeads(newSelection);
    };

    const handleEditContactClick = () => {
        if (selectedContacts.length === 1) {
            navigate(`/edit_contact/${selectedContacts[0]}`);
        }
    };

    const handleEditLeadClick = () => {
        if (selectedLeads.length === 1) {
            navigate(`/edit_lead/${selectedLeads[0]}`);
        }
    };

    const handleDeleteContactClick = () => {
        if (selectedContacts.length > 0) {
            console.log('Delete contact IDs:', selectedContacts);
        }
    };

    const handleDeleteLeadClick = () => {
        if (selectedLeads.length > 0) {
            console.log('Delete lead IDs:', selectedLeads);
        }
    };

    return (
        <>
            <MyAppBar />
            <Container maxWidth="xl" sx={{ marginBottom: '4rem' }}>
                <Box sx={{ display: 'flex', width: '100%', justifyContent: 'center', marginTop: '5rem' }}>
                    <Typography variant="h5" sx={{ marginY: '2rem' }}>
                        Daftar Kontak
                    </Typography>
                </Box>
                <Box sx={{ height: 400, width: '100%', mb: '2rem' }}>
                    <DataGrid
                        rows={contacts.map((contact, index) => ({ id: index + 1, ...contact }))}
                        columns={contactColumns}
                        pageSize={5}
                        rowsPerPageOptions={[5, 10, 25, 50, 100]}
                        checkboxSelection
                        onSelectionModelChange={handleContactSelectionChange}
                    />
                </Box>
                <Stack direction="row" spacing={2}>
                    <Button sx={{ textTransform: 'none' }} variant="outlined" component={Link} to="/add_contact">
                        <AddIcon />&nbsp;
                        Kontak Baru
                    </Button>
                    <Button
                        sx={{ textTransform: 'none' }}
                        variant="outlined"
                        disabled={selectedContacts.length !== 1}
                        onClick={handleEditContactClick}
                    >
                        <EditIcon />&nbsp;
                        Edit Kontak
                    </Button>
                    <Button
                        sx={{ textTransform: 'none' }}
                        variant="outlined"
                        color="error"
                        disabled={selectedContacts.length === 0}
                        onClick={handleDeleteContactClick}
                    >
                        <RemoveCircleOutlineIcon />&nbsp;
                        Hapus Kontak
                    </Button>
                    <Button sx={{ textTransform: 'none' }} variant="outlined" href="#">
                        <FormatListNumberedRtlOutlinedIcon />&nbsp;
                        Lihat Semua
                    </Button>
                </Stack>
                <Box sx={{ display: 'flex', width: '100%', justifyContent: 'center', marginTop: '6rem' }}>
                    <Typography variant="h5" sx={{ marginY: '2rem' }}>
                        Daftar Lead
                    </Typography>
                </Box>
                <Box sx={{ height: 400, width: '100%', mb: '2rem' }}>
                    <DataGrid
                        rows={leads.map((lead, index) => ({ id: index + 1, ...lead }))}
                        columns={leadColumns}
                        pageSize={5}
                        rowsPerPageOptions={[5]}
                        checkboxSelection
                        // 绑定Lead的选中事件
                        onSelectionModelChange={handleLeadSelectionChange}
                    />
                </Box>
                <Stack direction="row" spacing={2}>
                    <Button sx={{ textTransform: 'none' }} variant="outlined" component={Link} to="/add_lead">
                        <AddIcon />&nbsp;
                        Lead Baru
                    </Button>
                    <Button
                        sx={{ textTransform: 'none' }}
                        variant="outlined"
                        disabled={selectedLeads.length !== 1}
                        onClick={handleEditLeadClick}
                    >
                        <EditIcon />&nbsp;
                        Edit Lead
                    </Button>
                    <Button
                        sx={{ textTransform: 'none' }}
                        variant="outlined"
                        color="error"
                        disabled={selectedLeads.length === 0}
                        onClick={handleDeleteLeadClick}
                    >
                        <RemoveCircleOutlineIcon />&nbsp;
                        Hapus Lead
                    </Button>
                    <Button sx={{ textTransform: 'none' }} variant="outlined" href="#text-buttons">
                        <FormatListNumberedRtlOutlinedIcon />&nbsp;
                        Lihat Semua
                    </Button>
                </Stack>
            </Container>
        </>
    );
};

export default Dashboard;

内容的提问来源于stack exchange,提问作者luthfinzo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:15:01