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

React Modal更新条目Bug:每次更新同一ID问题排查

问题分析与解决方案

问题根源

  1. 闭包陷阱:所有模态框共用同一个modalState状态,点击保存时index会指向循环的最后一项,导致每次都更新同一条数据
  2. index不可靠:用map循环索引作为唯一ID,当数据增删或排序时index会变动,无法准确对应真实数据项
  3. 模态框状态混乱:多个模态框共享同一个显示状态,无法区分当前编辑的是哪条数据

修复步骤

1. 调整状态存储

将原有的modalState(布尔值)改为存储当前编辑项的唯一ID,初始值设为null:

const [editingId, setEditingId] = useState(null);

2. 修改模态框显示逻辑

每个模态框仅在editingId等于当前cardItem.id时才显示:

<Modal
  isOpen={editingId === cardItem.id}
  // 保留其他属性
>

3. 打开模态框时记录ID并初始化表单

给表格行添加打开模态框的触发事件,同时用当前项数据初始化Formik:

<tr id={cardItem.id}>
  <td>{cardItem.min}</td>
  <td>{cardItem.price}</td>
  <td>
    <Button onClick={() => {
      setEditingId(cardItem.id);
      formik.setValues({
        cardMinUp: cardItem.min,
        cardPriceUp: cardItem.price
      });
    }}>
      编辑
    </Button>
  </td>
</tr>

4. 提交时使用真实ID

保存时用cardItem.id作为更新的ID,替代循环index:

<Button
  onClick={() => {
    dispatch(
      agencySlice.editUpdateCardItem({
        id: cardItem.id,
        min: formik.values.cardMinUp,
        price: formik.values.cardPriceUp,
      })
    );
    setEditingId(null);
  }}
>
  Save
</Button>

完整修改后的代码片段

{cardItemData.map((cardItem) => (
<>
    <tr id={cardItem.id}>
        <td>{cardItem.min}</td>
        <td>{cardItem.price}</td>
        <td>
            <Button onClick={() => {
                setEditingId(cardItem.id);
                formik.setValues({
                    cardMinUp: cardItem.min,
                    cardPriceUp: cardItem.price
                });
            }}>
                编辑
            </Button>
        </td>
    </tr>

    <Modal
        titleId
        isOpen={editingId === cardItem.id}
        setIsOpen={() => setEditingId(null)}
        isStaticBackdrop
        isScrollable
        isCentered
        size
        isAnimation>
        <ModalHeader
            className
            setIsOpen={() => setEditingId(null)}>
            <ModalTitle id>
                Update
            </ModalTitle>
        </ModalHeader>
        <ModalBody>
            <div className='row'>
                <div className='col-lg-4'>
                    <FormGroup
                        id='cardMinUp'
                        label={t('form.cardMin')}
                        isFloating>
                        <Input
                            type='number'
                            placeholder={t('form.cardMin')}
                            isValid={formik.isValid}
                            value={formik.values.cardMinUp}
                            onChange={formik.handleChange}
                            isTouched={formik.touched.cardMinUp}
                            invalidFeedback={formik.errors.cardMinUp}
                        />
                    </FormGroup>
                </div>
                <div className='col-lg-4'>
                    <FormGroup
                        id='cardPriceUp'
                        label={t('form.cardPrice')}
                        isFloating>
                        <Input
                            type='number'
                            placeholder={t('form.cardPrice')}
                            isValid={formik.isValid}
                            value={formik.values.cardPriceUp}
                            onChange={formik.handleChange}
                            isTouched={formik.touched.cardPriceUp}
                            invalidFeedback={formik.errors.cardPriceUp}
                        />
                    </FormGroup>
                </div>
                <div className='col-lg-4 mt-2'>
                    <Button
                        onClick={() => {
                            dispatch(
                                agencySlice.editUpdateCardItem({
                                    id: cardItem.id,
                                    min: formik.values.cardMinUp,
                                    price: formik.values.cardPriceUp,
                                })
                            );
                            setEditingId(null);
                        }}
                        className='me-3'
                        icon='plus'
                        isOutline
                        color='info'>
                        Save
                    </Button>
                </div>
            </div>
        </ModalBody>
    </Modal>
</>
))}

关键注意事项

  • 确保每个cardItem拥有自己的唯一ID字段(如id),这是可靠区分数据项的基础
  • 避免在循环中依赖index作为数据标识,尤其是涉及增删改的场景
  • 每个模态框绑定独立的显示状态,避免共用布尔值导致的状态混乱

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 09:54:23