在可折叠 table reactjs 中使用地图

using map in collapsible table reactjs

我有一个可折叠的 table,看起来像 this。但是,当我单击一行时,两行都会展开。

这是我的代码的样子:

const Transaction = ({ categories }) => {
 const [open, setOpen] = useState(false);

let categoryList = categories.map((category, index) => {
    return (
        <TableRow key={index}>
          <TableCell>
            <IconButton size="small" onClick={() => setOpen(!open)}>
              {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
            </IconButton>
          </TableCell>
          <TableCell component="th" scope="row">
            {category}
          </TableCell>
          <TableCell />
          <TableCell />
          <TableCell />
          <TableCell />
        </TableRow>
      );
  });

 return (
    <div className={classes.root}>
      <Grid container spacing={2}>
        <Grid item xs={12}>
          <TableContainer component={Paper}>
            <Table>
              <TableHead>
                <TableRow>
                  <TableCell />
                  <TableCell>Category</TableCell>
                  <TableCell />
                  <TableCell />
                  <TableCell />
                  <TableCell />
                </TableRow>
              </TableHead>
              <TableBody>
                {categoryList}
              </TableBody>
            </Table>
          </TableContainer>
        </Grid>
      </Grid>
    </div>
  );
};

在我的 categoryList 中,我使用索引作为键,但它仍然扩展了两行而不是选定的特定行。我怎样才能只展开一行?

您的 table 行需要控制它们自己的 open 状态。目前,您构建代码的方式它们都共享相同的状态并且单击 table 行中的任何一个将引用相同的处理程序来更改 open 状态,所以这就是为什么您的 table 行同时打开和关闭。

因此,此解决方案不是让 open 保存单个布尔值,而是保存一个布尔值数组,这些布尔值最初都设置为 false。

    const [open, setOpen] = useState(categories.map(() => false));

这将创建一个大小为 categories 的布尔数组。

此外,OnClick 函数自然要稍作改动:

onClick={() => {
  setOpen((pOpen) => pOpen.map((o, i) => {
    if (i === index) return !o;
    return o;
  }));
}}

现在您可以使用索引 open[index] 了解打开的内容。

{open[index] ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}

完整代码段如下:

const Transaction = ({ categories }) => {
 /* 
  * Change this [Origninal]:
  * const [open, setOpen] = useState(false);
  * To this:
  */
 const [open, setOpen] = useState(categories.map(() => false));


  React.useEffect(() => {
    if (categories.length !== open.length) {
      setOpen(categories.map(() => false));
    }
  }, [categories, open]);


let categoryList = categories.map((category, index) => {
    return (
        <TableRow key={index}>
          <TableCell>
            <IconButton size="small" 
                        onClick={() => {
                          setOpen((pOpen) => pOpen.map((o, i) => {
                            if (i === index) return !o;
                            return o;
                          }));
                        }}
              {open[index] ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
            </IconButton>
          </TableCell>
          <TableCell component="th" scope="row">
            {category}
          </TableCell>
          <TableCell />
          <TableCell />
          <TableCell />
          <TableCell />
        </TableRow>
      );
  });

 return (
    <div className={classes.root}>
      <Grid container spacing={2}>
        <Grid item xs={12}>
          <TableContainer component={Paper}>
            <Table>
              <TableHead>
                <TableRow>
                  <TableCell />
                  <TableCell>Category</TableCell>
                  <TableCell />
                  <TableCell />
                  <TableCell />
                  <TableCell />
                </TableRow>
              </TableHead>
              <TableBody>
                {categoryList}
              </TableBody>
            </Table>
          </TableContainer>
        </Grid>
      </Grid>
    </div>
  );
};