React Modal更新条目Bug:每次更新同一ID问题排查
问题分析与解决方案
问题根源
- 闭包陷阱:所有模态框共用同一个
modalState状态,点击保存时index会指向循环的最后一项,导致每次都更新同一条数据 - index不可靠:用map循环索引作为唯一ID,当数据增删或排序时index会变动,无法准确对应真实数据项
- 模态框状态混乱:多个模态框共享同一个显示状态,无法区分当前编辑的是哪条数据
修复步骤
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
相关产品推荐
相关产品推荐

