ReactJs类组件(非Hooks)如何实现点击按钮仅更新当前行状态
问题修复方案
核心问题原因
原代码使用全局单一clicked状态控制所有行的按钮显示逻辑,只要状态变更所有行都会同步响应,才会出现点击任意行编辑按钮所有行都切换状态的问题。同时原代码直接操作DOM设置contenteditable属性,不符合React数据驱动视图的设计规范,容易出现状态和视图不同步的问题。
具体优化思路
- 将表格行数据抽离为结构化数组存入state,每条数据配置唯一id,新增
isEditing字段单独控制当前行的编辑状态 - 编辑、更新、取消操作均传入目标行的id,仅修改对应行的
isEditing状态,不影响其他行数据 - 渲染表格时使用
map遍历行数据,每行根据自身的isEditing值渲染对应按钮,同时直接通过状态控制单元格的contentEditable属性
完整修改后代码
import React from 'react'; class GridSample extends React.Component { constructor() { super(); this.state = { // 结构化存储表格数据,每条数据单独控制编辑状态 tableData: [ {id: 1, firstname: 'Jill', lastname: 'Smith', age: 50, isEditing: false}, {id: 2, firstname: 'Eve', lastname: 'Jackson', age: 94, isEditing: false}, {id: 3, firstname: 'John', lastname: 'Doe', age: 80, isEditing: false}, ] }; this.handleOnedit = this.handleOnedit.bind(this); this.handleCancel = this.handleCancel.bind(this); this.handleUpdate = this.handleUpdate.bind(this); this.handleOndelete = this.handleOndelete.bind(this); } // 传入行id,仅修改目标行的编辑状态 handleOnedit = (id) => { this.setState(prevState => ({ tableData: prevState.tableData.map(item => { if(item.id === id) { return {...item, isEditing: true} } return item }) })) }; handleOndelete() { alert('this is delete button'); } // 取消编辑,重置目标行状态 handleCancel(id) { this.setState(prevState => ({ tableData: prevState.tableData.map(item => { if(item.id === id) { return {...item, isEditing: false} } return item }) })) } // 更新完成后重置目标行状态 handleUpdate(id) { this.setState(prevState => ({ tableData: prevState.tableData.map(item => { if(item.id === id) { return {...item, isEditing: false} } return item }) })); // 此处可补充提交更新后数据的逻辑 } render() { console.clear(); return ( <div> <table> <thead> <tr> <th>Firstname</th> <th>Lastname</th> <th>Age</th> <th>Action</th> </tr> </thead> <tbody> {/* 遍历数据渲染行,每行用自身状态控制显示 */} {this.state.tableData.map(row => ( <tr key={row.id}> <td contentEditable={row.isEditing}>{row.firstname}</td> <td contentEditable={row.isEditing}>{row.lastname}</td> <td contentEditable={row.isEditing}>{row.age}</td> <td> {!row.isEditing ? ( <input type="button" value="Edit" onClick={() => this.handleOnedit(row.id)} /> ) : ( <input type="button" value="Update" onClick={() => this.handleUpdate(row.id)} /> )} {row.isEditing ? ( <input type="button" value="Cancel" onClick={() => this.handleCancel(row.id)} /> ) : ( <input type="button" value="Delete" onClick={this.handleOndelete} /> )} </td> </tr> ))} </tbody> </table> </div> ); } } export default GridSample;
内容的提问来源于stack exchange,提问作者Shubhangi Pant
相关产品推荐
相关产品推荐

