React中如何仅更新列表内单个元素对应的Modal操作状态
解决方案
核心问题
你当前的问题是所有列表项共用了全局的selectedValues、createAbleInputs状态,修改任意Modal的输入都会改变同一份全局数据,因此所有列表项都会展示相同内容。同时你未记录当前触发Modal的是哪个列表项,关闭Modal时无法将输入对应到目标条目。
修改步骤
- 调整状态结构:将存储选中内容的状态改为数组,每个数组元素对应一个列表项的独立输入结果
- 新增
activeIndex状态:记录当前打开Modal对应的列表项索引,点击打开按钮时传入当前条目索引 - 新增Modal临时输入状态:Modal内的输入先存在临时状态中,关闭时再将临时状态的数据同步到对应索引的列表项状态中
- 渲染逻辑调整:每个列表项仅读取自身索引对应的状态内容展示
修改后核心代码
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
相关产品推荐
相关产品推荐

