首页 > 解决方案 > 在可折叠表reactjs中使用地图

问题描述

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

这就是我的代码的样子:

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 中,我使用 index 作为键,但它仍然扩展两行而不是选定的特定行。我怎样才能只扩展一行?

标签: reactjsloopsdictionaryindexingkey

解决方案


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

因此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>
  );
};

推荐阅读