如何在MUI X Data Grid的renderCell组件间传值实现Select联动
解决MUI X DataGrid中联动Select组件的状态传递问题
问题场景
在MUI X DataGrid中,新增行时第一列是选择文件的Select组件,第二列是选择参数的Select组件,要求参数的选项随选中的文件动态变化,但使用renderCell渲染组件时,两个组件的状态无法联动。
给定数据源:
const data = { "/path/to/file1.csv": { parameters: ["Parameter 1", "Parameter 2", "Parameter 3"], }, "/path/to/file2.csv": { parameters: ["Parameter 2", "Parameter 3", "Parameter 4"], }, "/path/to/file3.csv": { parameters: ["Parameter 5", "Parameter 6", "Parameter 7"], }, };
核心解决方案
将每行的选中状态(文件、参数)统一维护在rows数组中作为单一数据源。当文件选择变化时,更新对应行的选中文件,并同步更新该行的可选参数列表;参数选择变化时直接更新对应行的选中参数。通过修改rows触发DataGrid重新渲染,实现组件联动。
修改后的完整代码
import * as React from "react"; import PropTypes from "prop-types"; import { Button, Select, MenuItem } from "@mui/material"; import DeleteIcon from "@mui/icons-material/Delete"; import { DataGrid, GridActionsCellItem } from "@mui/x-data-grid"; const FileSelect = (props) => { const { params, files, data, updateRow } = props; const { row } = params; const handleChange = (event) => { const selectedFile = event.target.value; // 更新行的选中文件,同步可选参数并清空之前的参数选择 updateRow(row.id, { selectedFile, availableParams: selectedFile ? data[selectedFile].parameters : [], selectedParam: "" }); }; return ( <Select value={row.selectedFile || ""} onChange={handleChange} fullWidth placeholder="选择文件" > {files.map((item, index) => ( <MenuItem key={index} value={item}> {item} </MenuItem> ))} </Select> ); }; FileSelect.propTypes = { params: PropTypes.object.isRequired, files: PropTypes.array.isRequired, data: PropTypes.object.isRequired, updateRow: PropTypes.func.isRequired, }; const ParameterSelect = (props) => { const { params, updateRow } = props; const { row } = params; const handleChange = (event) => { updateRow(row.id, { selectedParam: event.target.value }); }; return ( <Select value={row.selectedParam || ""} onChange={handleChange} fullWidth disabled={!row.availableParams?.length} placeholder="选择参数" > {row.availableParams?.map((item, index) => ( <MenuItem key={index} value={item}> {item} </MenuItem> ))} </Select> ); }; ParameterSelect.propTypes = { params: PropTypes.object.isRequired, updateRow: PropTypes.func.isRequired, }; export default function DataGridTable(props) { const { data } = props; const files = Object.keys(data); const [rows, setRows] = React.useState([]); // 更新指定行数据的通用函数 const updateRow = (rowId, updates) => { setRows(prevRows => prevRows.map(row => row.id === rowId ? { ...row, ...updates } : row ) ); }; const columns = [ { field: "file", headerName: "File", flex: 1, renderCell: (params) => ( <FileSelect params={params} files={files} data={data} updateRow={updateRow} /> ), }, { field: "x", headerName: "X", flex: 0.5, renderCell: (params) => ( <ParameterSelect params={params} updateRow={updateRow} /> ), }, { field: "actions", headerName: "Delete", type: "actions", width: 80, getActions: (params) => [ <GridActionsCellItem icon={<DeleteIcon />} label="Delete" onClick={() => deleteRow(params.id)} />, ], }, ]; const handleClick = () => { const newRow = { id: rows.length + 1, selectedFile: "", availableParams: [], selectedParam: "" }; setRows(prevState => [...prevState, newRow]); }; const deleteRow = (id) => { setRows(prevRows => prevRows.filter(row => row.id !== id)); }; return ( <div> <Button variant="contained" onClick={handleClick}> Add row </Button> <div style={{ height: 300, width: "100%" }}> <DataGrid rows={rows} columns={columns} disableSelectionOnClick /> </div> </div> ); }
关键修改点说明
- 行数据结构优化:新增行时存储
selectedFile(选中的文件)、availableParams(当前文件对应的可选参数)、selectedParam(选中的参数),不再将文件列表存入行数据。 - 状态统一管理:移除两个Select组件内部的
useState,改用rows中的行数据作为状态来源,通过updateRow函数统一更新行数据。 - 联动逻辑实现:选中文件时,同步更新该行的
availableParams,ParameterSelect会自动根据新的参数列表渲染选项,同时清空之前的参数选择。 - 交互体验优化:当没有可选参数时,ParameterSelect自动禁用,避免无效操作。
内容的提问来源于stack exchange,提问作者Simon1
相关产品推荐
相关产品推荐

