当另一个Select组件使用DataGrid更改时,如何更改一个Select组件的MenuItems?我需要能够将一个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"],
  },
};

在我的DataGrid表中,每次我通过单击按钮添加新行时,第一个单元格都有一个包含Object.keys(data)Select组件.

第二个单元格包含另一个Select分量.我希望这个Select组件包含依赖于所选值的参数.例如,如果 Select /path/to/file1.csv,我想使这些参数可用(Parameter 1, Parameter 2, Parameter 3),但如果 Select /path/to/file3.csv,我想使那些参数可用(Parameter 5, Parameter 6, Parameter 7).

以下是我的组件:

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 { value } = props;
  const [file, setFile] = React.useState("");

  const handleChange = (event) => {
    setFile(event.target.value);
  };

  return (
    <Select id="file-select" value={file} onChange={handleChange} fullWidth>
      {value?.map((item, index) => (
        <MenuItem key={index} value={item}>
          {item}
        </MenuItem>
      ))}
    </Select>
  );
};

FileSelect.propTypes = {
  value: PropTypes.array,
};

const ParameterSelect = (props) => {
  const { value } = props;
  const [parameter, setParameter] = React.useState("");

  const handleChange = (event) => {
    setParameter(event.target.value);
  };

  return (
    <Select
      id="parameter-select"
      value={parameter}
      onChange={handleChange}
      fullWidth
    >
      {value?.map((item, index) => (
        <MenuItem key={index} value={item}>
          {item}
        </MenuItem>
      ))}
    </Select>
  );
};

export default function DataGridTable(props) {
  const { data } = props;
  const files = Object.keys(data);

  const [rows, setRows] = React.useState([]);

  const columns = [
    {
      field: "file",
      headerName: "File",
      // width: 200,
      flex: 1,
      renderCell: FileSelect,
    },
    {
      field: "x",
      headerName: "X",
      // width: 200,
      flex: 0.5,
      renderCell: ParameterSelect,
    },
    {
      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,
      file: files,
      x: [],
    };
    setRows((prevState) => [...prevState, newRow]);
  };

  const deleteRow = React.useCallback(
    (id) => () => {
      setTimeout(() => {
        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>
  );
}

推荐答案

我认为实现这一点的最简单方法是在列定义中添加一个额外的字段,作为存储所选值的"简单"位置.

...

const FileSelect = (props) => {
  const { value, row } = props;

  const [file, setFile] = React.useState("");

  const handleChange = (event) => {
    setFile(event.target.value);
    // Set the value here
    row.selectedFile = event.target.value;
  };

  return (
    <Select id="file-select" value={file} onChange={handleChange} fullWidth>
      {value?.map((item, index) => (
        <MenuItem key={index} value={item}>
          {item}
        </MenuItem>
      ))}
    </Select>
  );
};

...

{
   field: "selectedFile",
   hideable: true
},

...

然后在selectedFile列的FileSelect父值中设置所选值(文件).然后,剩下的工作就是使parameters个查询值对ParameterSelect可用.同样,我只是把它们塞进了renderCell个props ,但这个也可以做得更好:

...

{
   field: "x",
   headerName: "X",
   flex: 0.5,
   // Passing the entire original data in as an extra param, for demonstration purposes
   renderCell: (props) => ParameterSelect({ ...props, data })
},

...

最后,只需隐藏selectedFile列:

...

<DataGrid
  rows={rows}
  columns={columns}
  disableSelectionOnClick
  // Hiding the extra field
  columnVisibilityModel={{
     selectedFile: false
  }}
/>

...

制作这个:(I changed your values to make them easier to read while I was working)

I think this is what you wanted

Working CodeSandBox:https://codesandbox.io/s/prod-sun-bdvcu0?file=/demo.js:842-854

Reactjs相关问答推荐

从`redux—thunk`导入thunk `在stackblitz中不起作用

react 副作用循环

useTranslation不会在languageChanged上重新呈现组件

在下一个js中使用ESTAccountWithEmailAndPassword函数时循环

在Reaction常量函数中未更新状态变量

MUiv5和TSS-Reaction SSR问题:无法可靠地处理样式定义.CSSprops 中的ArrowFunctionExpression

使用自动播放的视频组件呈现登录页面时出现JEST测试错误

为什么在页面重新加载时Location.State变得未定义?

useRef 不关注模态

React Router 6 点击链接在 React 18 应用中打开 flickr 页面

无法在 reactJS 中使用空包装器 <>

使用 React.lazy 调试 webpack 代码拆分

更新 Next.js 路由查询更改的状态会导致无限循环

ReactJS:useMemo 钩子修复了我的无限重新渲染问题而不是 useEffect

错误:无效挂钩调用.钩子只能在函数组件的主体内部调用.使用 next/router 时

渲染的钩子比预期的少.这可能是由 React Hooks 中意外的提前返回语句引起的

gtag:为什么谷歌分析即使没有被授权也会收集数据

bootstrap 导航栏切换器在 reactjs 中不起作用

为什么这两个 div 的渲染方式不同?

如何在 NavBar 中设置动态标题