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

MUI X Data Grid rowMouseEnter事件失效及行内按钮样式切换问题

问题描述
  • 需求:鼠标悬停在DataGrid任意行时,将“Analyze”按钮从outlined变体切换为contained变体
  • 问题:rowMouseEnter事件无法触发,同时不清楚如何在鼠标悬停行时更新该行内的单元格
  • 依赖版本:
"@mui/x-data-grid": "^5.17.25",
"@mui/x-data-grid-generator": "^6.0.0",
"@mui/x-data-grid-pro": "^6.0.0",

代码实现

import React, { useRef, useState, useEffect } from "react";
import { DataGrid, GridRowsProp, GridColDef } from "@mui/x-data-grid";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import { useTheme } from "@mui/system";
import Link from "next/link";
import TextField from "@mui/material/TextField";
import InputAdornment from "@mui/material/InputAdornment";
import SearchIcon from "@mui/icons-material/Search";
import AddIcon from "@mui/icons-material/Add";
import CircularProgress from "@mui/material/CircularProgress";
import { alpha, styled, lighten } from "@mui/material/styles";

export default function PropertiesList({ newProperties }) {
  const theme = useTheme();
  const boxRef = useRef(null);
  const [searchText, setSearchText] = useState("");
  const columns = getColumns(theme);

  function getColumns(theme) {
    // commented because irrelevant
    return [
      {
        field: "id",
        headerName: "Actions",
        width: 150,
        renderCell: (params) => {
          return (
            <Box
              sx={{
                display: "flex",
                justifyContent: "space-between",
                width: "100%"
              }}
            >
              <Link
                href="/properties/[id]"
                as={`/properties/${params.row.original_doc || params.row.id}`}
              >
                <Button
                  size="small"
                  variant="outlined"
                  startIcon={<CalculateIcon />}
                  sx={{
                    backgroundColor:
                      hoveredRowId === params.id
                        ? theme.palette.success.main
                        : ""
                  }}
                >
                  Analyze
                </Button>
              </Link>
            </Box>
          );
        }
      }
    ];
  }

  useEffect(() => {
    if (!boxRef.current) return;
    const screenHeight = window.innerHeight;
    boxRef.current.style.height = `${screenHeight - 120}px`;
  }, []);

  const handleRowOver = (params) => {
    // change the analyze button from "outlined" to "contained" when hovered.
    // The below console.log does not trigger.
    console.log(`Row ${params.id} is being hovered over`);
  };

  return (
    <Box ref={boxRef}>
      {!newProperties && (
        <Box
          sx={{
            height: "calc(100vh - 160px)",
            display: "flex",
            justifyContent: "center",
            alignItems: "center"
          }}
        >
          <CircularProgress size={32} />
        </Box>
      )}
      {newProperties && (
        <>
          <Box
            sx={{
              display: "flex",
              justifyContent: "space-between",
              alignItems: "center",
              background: theme.palette.background.background2,
              marginTop: 3,
              // marginBottom: 1,
              padding: 2,
              border: "1px solid " + theme.palette.contrast.contrast1,
              borderTopLeftRadius: 8,
              borderTopRightRadius: 8
            }}
          >
            <TextField
              label="Search for property"
              placeholder=""
              sx={{ marginTop: 1, marginBottom: 1 }}
              onChange={(event) => setSearchText(event.target.value)}
              InputProps={{
                startAdornment: (
                  <InputAdornment position="start">
                    <SearchIcon />
                  </InputAdornment>
                )
              }}
            />

            <Link href="/properties/add">
              <Button
                size="medium"
                variant="contained"
                sx={{ height: 50 }}
                startIcon={<AddIcon />}
              >
                Add Property
              </Button>
            </Link>
          </Box>

          <DataGrid
            rowMouseEnter={handleRowOver}
            sx={{
              border: "1px solid " + theme.palette.contrast.contrast1,
              height: "calc(100vh - 280px)",
              background: theme.palette.background.background1,
              "& .MuiDataGrid-virtualScroller::-webkit-scrollbar": {
                height: "0.4em",
                width: "0.4em"
              },
              "& .MuiDataGrid-virtualScroller::-webkit-scrollbar-track": {
                background: theme.palette.contrast.contrast1
              },
              "& .MuiDataGrid-virtualScroller::-webkit-scrollbar-thumb": {
                backgroundColor: theme.palette.contrast.contrast2
              },
              "& .MuiDataGrid-virtualScroller::-webkit-scrollbar-thumb:hover": {
                background: theme.palette.contrast.default
              },
              borderTopLeftRadius: 0,
              borderTopRightRadius: 0,
              borderBottomLeftRadius: 8,
              borderBottomRightRadius: 8
            }}
            rows={newProperties.filter(
              (row) =>
                (row.address &&
                  row.address
                    .toLowerCase()
                    .includes(searchText.toLowerCase())) ||
                (row.city &&
                  row.city.toLowerCase().includes(searchText.toLowerCase())) ||
                (row.state &&
                  row.state.toLowerCase().includes(searchText.toLowerCase())) ||
                (row.zip &&
                  row.zip
                    .toString()
                    .toLowerCase()
                    .includes(searchText.toLowerCase()))
            )}
            columns={columns}
            pageSize={13}
            disableColumnFilter
            disableSelectionOnClick
            disableColumnSelector
          />
        </>
      )}
    </Box>
  );
}
解决方案

1. 修复事件不触发问题

你混用了MUI X v5和v6版本的包,导致事件名不匹配:

  • v5版本的DataGrid行鼠标进入事件名为onRowMouseEnter(带on前缀)
  • v6版本的事件名为rowMouseEnter(无on前缀)

当前你安装的@mui/x-data-grid是v5.17.25,所以需要修改事件绑定:

<DataGrid
  onRowMouseEnter={handleRowOver}
  // 其他属性保持不变
/>

2. 实现按钮变体切换逻辑

步骤1:添加状态跟踪悬停行ID

在组件内部新增状态变量:

const [hoveredRowId, setHoveredRowId] = useState(null);

步骤2:完善事件处理函数

添加鼠标离开行的处理函数,清除悬停状态:

const handleRowOver = (params) => {
  setHoveredRowId(params.id);
};

const handleRowLeave = () => {
  setHoveredRowId(null);
};

然后在DataGrid上绑定离开事件:

<DataGrid
  onRowMouseEnter={handleRowOver}
  onRowMouseLeave={handleRowLeave}
  // 其他属性保持不变
/>

步骤3:动态切换按钮变体

修改renderCell中的按钮组件,根据hoveredRowId切换variant和样式:

<Button
  size="small"
  variant={hoveredRowId === params.id ? "contained" : "outlined"}
  startIcon={<CalculateIcon />}
  sx={{
    backgroundColor: hoveredRowId === params.id 
      ? theme.palette.success.main 
      : "transparent",
    color: hoveredRowId === params.id 
      ? theme.palette.success.contrastText 
      : theme.palette.success.main
  }}
>
  Analyze
</Button>

步骤4:修复列配置的渲染问题

当前columns定义在组件顶层,状态变化时不会重新生成列配置,需要把列配置移到组件内部,确保hoveredRowId变化时能触发单元格重渲染:

// 把columns定义移到组件内部
const columns = [
  {
    field: "id",
    headerName: "Actions",
    width: 150,
    renderCell: (params) => {
      return (
        <Box
          sx={{
            display: "flex",
            justifyContent: "space-between",
            width: "100%"
          }}
        >
          <Link
            href="/properties/[id]"
            as={`/properties/${params.row.original_doc || params.row.id}`}
          >
            <Button
              size="small"
              variant={hoveredRowId === params.id ? "contained" : "outlined"}
              startIcon={<CalculateIcon />}
              sx={{
                backgroundColor: hoveredRowId === params.id 
                  ? theme.palette.success.main 
                  : "transparent",
                color: hoveredRowId === params.id 
                  ? theme.palette.success.contrastText 
                  : theme.palette.success.main
              }}
            >
              Analyze
            </Button>
          </Link>
        </Box>
      );
    }
  }
];

3. 统一MUI X版本(可选但推荐)

混用v5和v6包容易引发兼容性问题,建议统一升级到同一大版本,比如全部升级到v6:

"@mui/x-data-grid": "^6.0.0",
"@mui/x-data-grid-generator": "^6.0.0",
"@mui/x-data-grid-pro": "^6.0.0",

如果使用v6版本,事件名改回rowMouseEnter和rowMouseLeave即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 06:32:16