React .map渲染列表时如何仅让点击编辑的项切换编辑状态
问题原因
你当前所有列表项共用了isShow、unShow两个全局布尔状态,只要状态更新,所有map渲染的项都会读取到同一个状态值,自然会全部切换成编辑态,和你点的是哪一项没有关联。
解决方案
核心思路:不要用全局布尔值控制编辑态,改为存储当前处于编辑状态的行ID,每一行渲染时单独判断自身ID是否匹配编辑ID,再决定显示文本还是输入框。
- 第一步:替换原有状态定义
删掉原来的isShow、unShow两个布尔状态,新增一个存储编辑行ID的状态:// 默认值为null,代表无行处于编辑状态 const [editingId, setEditingId] = useState(null) - 第二步:把事件处理函数移到map循环外部(避免每次渲染重复创建函数),修改切换逻辑:
// 点击编辑/取消按钮的逻辑 const handleEditToggle = (id) => { // 如果当前点击的行已经是编辑态,就退出编辑(设为null),否则把当前行id设为编辑态 setEditingId(currentId => currentId === id ? null : id) } // 编辑确认逻辑,提交后退出编辑态 const handleEditConfirm = () => { // 这里写你原来的提交保存逻辑 // ... // 保存完成后退出编辑 setEditingId(null) } - 第三步:修改列表渲染逻辑,每一行单独判断是否为当前编辑项
注意:列表key建议用数据唯一IDval._id,不要用map遍历的索引key,避免列表顺序变动时出现渲染bug。<tbody> {carsList.map((val) => { // 判断当前行是否处于编辑态 const isEditing = editingId === val._id return ( <tr key={val._id}> <th scope='row'> {isEditing ? ( <input type="text" onChange={(event) => {newsetCarsName(event.target.value)}} defaultValue={val.carsName} /> ) : ( <p>{val.carsName}</p> )} </th> <th scope='row'> {isEditing ? ( <input type="text" onChange={(event) => {newsetModel(event.target.value)}} defaultValue={val.carsModels} /> ) : ( <p>{val.carsModels}</p> )} </th> <th scope='row'> {isEditing ? ( <input type="text" onChange={(event) => {newsetDate(event.target.value)}} defaultValue={val.carsDate} /> ) : ( <p>{val.carsDate}</p> )} </th> <th scope='row'> {isEditing ? ( <input type="text" onChange={(event) => {newsetNbkm(event.target.value)}} defaultValue={val.carsNbkm} /> ) : ( <p>{val.carsNbkm}</p> )} </th> <th scope='row'> {isEditing ? ( <input type="text" onChange={(event) => {newsetPrice(event.target.value)}} defaultValue={val.carsPrice} /> ) : ( <p>{val.carsPrice}</p> )} </th> <th scope='row'> {isEditing ? ( <input type="text" onChange={(event) => {newsetPowch(event.target.value)}} defaultValue={val.carsPowch} /> ) : ( <p>{val.carsPowch}</p> )} </th> <th scope='row'> <button onClick={() => Delete(val._id)}>Delete</button> </th> <th scope='row'> {isEditing && (<button onClick={handleEditConfirm}>Modifier</button>)} {!isEditing && (<button onClick={() => handleEditToggle(val._id)}>Edit</button>)} {isEditing && (<button onClick={() => handleEditToggle(val._id)}>Annuler</button>)} </th> </tr> ) })} </tbody>
补充说明
原来的input用placeholder展示原有值不符合交互逻辑,改成defaultValue直接把原有值填充到输入框里,用户编辑时不需要从头输入。
内容的提问来源于stack exchange,提问作者Nivekyr
相关产品推荐
相关产品推荐

