首页 > 解决方案 > 如何在 ReactJS 中将数据传递给 Material UI 'Table' 组件

问题描述

我正在使用 materialUI 的内置组件之一在我的一个站点上显示数据。目前,实现的代码非常接近 MaterialUI API 站点上的示例。话虽如此,我已经为我自己的个人用例做了一些调整。这就是我需要的每一列的标记方式(总共 5 个)。我还在下面包含了我的代码。

自定义表

import React from 'react';
import {
  withStyles,
  Theme,
  createStyles,
  makeStyles,
} from '@material-ui/core/styles';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableContainer from '@material-ui/core/TableContainer';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import Paper from '@material-ui/core/Paper';

const StyledTableCell = withStyles((theme: Theme) =>
  createStyles({
    head: {
      backgroundColor: '#533cf8',
      color: theme.palette.common.white,
      fontSize: 11,
    },
    body: {
      fontSize: 10,
    },
  }),
)(TableCell);

const StyledTableRow = withStyles((theme: Theme) =>
  createStyles({
    root: {
      '&:nth-of-type(odd)': {
        backgroundColor: theme.palette.action.hover,
      },
    },
  }),
)(TableRow);

function createData(
  parameters: string,
  required: string,
  description: string,
  defaults: string,
  type: string,
) {
  return { parameters, required, description, defaults, type };
}

const rows = [
  createData('id', 'yes', 'id to update', 'n/a', 'string'),
  // eslint-disable-next-line prettier/prettier
  createData('start', 'no', 'datetime in YYYY-MM-DD HH:mm:ss format that specifies the start', 'n/a', 'string',),
  // eslint-disable-next-line prettier/prettier
  createData('end', 'no', 'datetime string in YYYY-MM-DD HH:mm:ss format that specifies the end', 'n/a', 'string',),
  // eslint-disable-next-line prettier/prettier
  createData('provider', 'no', 'subdomain of the provider this affects', 'n/a', 'string',),
  createData('resources', 'no', 'list of ids for resources', 'n/a', 'string[]'),
];

const useStyles = makeStyles({
  main: {
    maxWidth: '90%',
    marginRight: 'auto',
    marginBottom: '75px',
    marginLeft: '25px',
    borderRadius: '8px',
  },
});

export default function CustomTable(): JSX.Element {
  const classes = useStyles();

  return (
    <TableContainer
      component={Paper}
      className={classes.main}
      elevation={0}
      style={{
        borderRight: '0.3px solid lightgray',
        borderLeft: '0.3px solid lightgray',
      }}
    >
      <Table aria-label="customized table">
        <TableHead>
          <TableRow>
            <StyledTableCell>Parameters</StyledTableCell>
            <StyledTableCell align="right">Required</StyledTableCell>
            <StyledTableCell align="right">Description&nbsp;</StyledTableCell>
            <StyledTableCell align="right">Defaults&nbsp;</StyledTableCell>
            <StyledTableCell align="right">Type&nbsp;</StyledTableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {rows.map((row) => (
            <StyledTableRow key={row.parameters}>
              <StyledTableCell component="th" scope="row">
                {row.parameters}
              </StyledTableCell>
              <StyledTableCell align="right">{row.required}</StyledTableCell>
              <StyledTableCell align="right">{row.description}</StyledTableCell>
              <StyledTableCell align="right">{row.defaults}</StyledTableCell>
              <StyledTableCell align="right">{row.type}</StyledTableCell>
            </StyledTableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
}

对于我的项目,我将多次使用这张表。列标题不会改变,但行/参数的数量肯定会改变。例如,可能有一个表只有 2 行,而另一个可能有多达 8 行。

在我当前的代码中,表格是使用“const rows”变量填充的,但是由于我在整个站点中都使用这个组件,所以我想使用 props/variables 传递类似的东西,而不是每次都创建一个新组件我想用数据填充表格。我对 ReactJS 比较陌生,因此非常感谢任何帮助。谢谢你。

标签: javascriptreactjstypescriptmaterial-uireact-props

解决方案


You have the right idea about passing props to your CustomTable component to be able to change the data that gets rendered. Then, the parent component can pass the rows through the CustomTable component's props.

Here's a simplified example

interface Row {
  id: string;
  data: string;
}

export interface TableProps {
  rows: Row[];
}

// Not really a table
export function Table({ rows }: TableProps) {
  return (
    <>
      {rows.map((row) => (
        <div key={row.id}>{row.data}</div>
      ))}
    </>
  );
}

const rows: Row[] = [
  { id: "0", data: "foo" },
  { id: "1", data: "bar" },
  { id: "2", data: "baz" }
];

export default function App() {
  return (
    <div className="App">
      <Table rows={rows} />
    </div>
  );
}

And an interactive one:

const { useState, Fragment } = React;

const Table = ({ rows }) => {
  return (
    <Fragment>
      {rows.map((row) => (
        <div key={row.id}>{row.data}</div>
      ))}
    </Fragment>
  );
}


const App = () => {
  const [rows, setRows] = useState([]);
  const [value, setValue] = useState('');
  
  const handleChange = (e) => {
    setValue(e.target.value);
  }
  
  const handleSubmit = (e) => {
    e.preventDefault();
    setValue('');
    setRows((state) => [...state, {id: uuidv4(), data: value}]);
  };
  
  return (
    <div>
      <Table rows={rows} />
      <form onSubmit={handleSubmit}>
        <label>
          Data
          <input value={value} onChange={handleChange} />
        </label>
        <button type="submit">Add row</button>
      </form>
    </div>
  );
}

ReactDOM.render(<App />, document.body);
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/uuid@latest/dist/umd/uuidv4.min.js"></script>


推荐阅读