You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何仅更新列表内单个元素对应的Modal操作状态

解决方案

核心问题

你当前的问题是所有列表项共用了全局的selectedValues、createAbleInputs状态,修改任意Modal的输入都会改变同一份全局数据,因此所有列表项都会展示相同内容。同时你未记录当前触发Modal的是哪个列表项,关闭Modal时无法将输入对应到目标条目。

修改步骤

  1. 调整状态结构:将存储选中内容的状态改为数组,每个数组元素对应一个列表项的独立输入结果
  2. 新增activeIndex状态:记录当前打开Modal对应的列表项索引,点击打开按钮时传入当前条目索引
  3. 新增Modal临时输入状态:Modal内的输入先存在临时状态中,关闭时再将临时状态的数据同步到对应索引的列表项状态中
  4. 渲染逻辑调整:每个列表项仅读取自身索引对应的状态内容展示

修改后核心代码

export default () => {
  const [open, setOpen] = React.useState(false);
  // 记录当前操作的列表项索引
  const [activeIndex, setActiveIndex] = React.useState(-1);
  // Modal内临时输入状态
  const [tempSelectedValues, setTempSelectedValues] = React.useState([]);
  const [tempCreateAbleInputs, setTempCreateAbleInputs] = React.useState([]);
  // 所有列表项的独立存储状态,每个元素对应一条的输入结果
  const [allItemValues, setAllItemValues] = React.useState(
    // 初始值和列表长度一致,每个项初始为空
    [{ selected: [], createAble: [] }, { selected: [], createAble: [] }]
  );
  const [country] = React.useState([
    { value: "1", label: "a" },
    { value: "2", label: "b" },
    { value: "3", label: "c" }
  ]);

  function handleClickOpen(index) {
    setActiveIndex(index);
    // 打开Modal前清空临时输入
    setTempSelectedValues([]);
    setTempCreateAbleInputs([]);
    setOpen(true);
  }

  function handleClose() {
    // 将临时输入同步到对应索引的列表项状态中
    if (activeIndex > -1) {
      const newValues = [...allItemValues];
      newValues[activeIndex] = {
        selected: tempSelectedValues,
        createAble: tempCreateAbleInputs
      };
      setAllItemValues(newValues);
    }
    setActiveIndex(-1);
    setOpen(false);
  }

  const a = [{ name: "a" }, { name: "b" }];
  const classes = useStyles();

  return (
    <Fragment>
      {a.map((item, index) => {
        // 仅读取当前条目对应的输入内容
        const combinedArray = [
          ...allItemValues[index].selected,
          ...allItemValues[index].createAble
        ];
        return (
          <div key={index}>
            <Button onClick={() => handleClickOpen(index)}>ModalButton</Button>
            <div>
              Modal内选中的选项为:{" "}
              {combinedArray?.length
                ? combinedArray.map((item, idx) =>
                    idx !== 0 ? `, ${item.label}` : item.label
                  )
                : ""}
            </div>
          </div>
        );
      })}

      <Dialog
        maxWidth={"sm"}
        fullWidth={true}
        open={open}
        onClose={handleClose}
        aria-labelledby="alert-dialog-title"
        aria-describedby="alert-dialog-description"
        classes={{
          paperFullWidth: classes.paperFullWidth
        }}
      >
        <DialogTitle id="alert-dialog-title">Dialog</DialogTitle>
        <DialogContent
          classes={{
            root: classes.dialogContentRoot
          }}
        >
          <Grid container spacing={2}>
            <Grid item xs={6}>
              <FormControl style={{ width: "100%" }}>
                <ReactSelect
                  handleSelectValues={setTempSelectedValues}
                  isMulti={true}
                  options={country}
                />
              </FormControl>
            </Grid>
          </Grid>
          <Grid container spacing={2}>
            <CreatableInputOnly handleSelectValues={setTempCreateAbleInputs} />
          </Grid>
        </DialogContent>
        <DialogActions>
          <Button onClick={handleClose} variant="contained">
            Close
          </Button>
        </DialogActions>
      </Dialog>
    </Fragment>
  );
};

内容的提问来源于stack exchange,提问作者Catarina Nogueira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 09:09:00