Ag-Grid可编辑表格动态添加行:仅最后一行显示Add按钮异常排查
AgGrid 动态显示Add按钮异常修复
问题说明
在React函数组件中实现可编辑AgGrid,最后一列通过自定义cellRenderer实现Add/Remove按钮,需求为仅最后一行显示Add按钮。初始渲染时最后一行(第2行)正常显示Add按钮,但点击按钮添加新行后,原第2行的Add按钮未消失,导致出现多个Add按钮。
问题代码
父组件代码
const MyCmp = (props) => { const getData = () => { return [{ id: 0, firstName: 'F1', lastName: 'L1' }, { id: 1, firstName: 'F2', lastName: 'L2', }]; } const [myCols, setMyCols] = useState(null); const [gridData, setGridData] = useState(getData()); const [gridApi, setGridApi] = useState(''); let cellRules = { 'rag-red': params => { if (params.data.lastName === 'INVALID_VAL') { return true; } } }; const handleGridReady = (params) => { setGridApi(params.api); setMyCols([{ headerName: 'F Name', field: 'firstName', editable: true }, { headerName: 'L Name', field: 'lastName', cellClassRules: cellRules, editable: true }, { headerName: '', field: 'buttonCol', cellRenderer: 'customColRenderer', cellRendererParams: { addItems: addItems } }] ); }; const createNewRowData = () => { const newData = { id: newCount, firstName: '', lastName: '' }; newCount++; return newData; } let newCount = getData().length; const addItems = (addIndex, props) => { const newItems = [createNewRowData()]; const res = props.api.applyTransaction({ add: newItems, addIndex: addIndex, }); setGridData(...gridData, res.add[0].data); // IS THIS CORRECT ? if (props.api.getDisplayedRowCount() > props.api.paginationGetPageSize()) { props.api.paginationGoToPage(parseInt((props.api.getDisplayedRowCount() / props.api.paginationGetPageSize())) + 1); } } const onCellClicked = (e) => { } const frameworkComponents = () => { return {customColRenderer: customColRenderer} } return ( <> <MyAgGrid id="myGrid" columnDefs={myCols} rowData={gridData} frameworkComponents={{customColRenderer: customColRenderer}} {...props} /> </> ) }
自定义Cell Renderer代码
export default (props) => { let isLastRow = (props.rowIndex === (props.api.getDisplayedRowCount() -1)) ? true: false; const addItems = (addIndex) => { props.addItems(addIndex, props); } return ( <span> {isLastRow ? <button onClick={() => addItems()}>Add</button> : null} <span><button onClick={() => props.api.applyTransaction({remove: props.api.getSelectedRows()})}>Remove</button> </span> ); };
问题原因
- Cell Renderer未自动刷新:AgGrid的单元格渲染器默认不会因行顺序变化重新渲染,添加新行后原行的
isLastRow判断未更新。 - 状态更新逻辑错误:
setGridData(...gridData, res.add[0].data)错误地将数组拆分为多个参数传递,未正确更新gridData状态。 - 变量作用域问题:
newCount定义在组件函数内部,每次组件渲染都会重置,导致新增行ID计算错误。 isLastRow判断不够可靠:依赖rowIndex和getDisplayedRowCount的组合,在分页或行过滤场景下可能失效。
修复方案
1. 强制刷新按钮列单元格
添加新行后,调用refreshCells触发按钮列重新渲染,让所有行重新判断是否为最后一行:
const addItems = (addIndex, props) => { const newItems = [createNewRowData()]; const res = props.api.applyTransaction({ add: newItems, addIndex: addIndex, }); // 正确更新gridData状态 setGridData(prev => [...prev, res.add[0].data]); // 强制刷新按钮列,重新计算isLastRow props.api.refreshCells({ force: true, columns: ['buttonCol'] }); if (props.api.getDisplayedRowCount() > props.api.paginationGetPageSize()) { props.api.paginationGoToPage(parseInt((props.api.getDisplayedRowCount() / props.api.paginationGetPageSize())) + 1); } }
2. 修正gridData状态更新方式
使用函数式更新确保基于最新状态创建新数组:
setGridData(prevGridData => [...prevGridData, res.add[0].data]);
3. 用useRef保存newCount
避免组件渲染时重置计数:
import { useRef } from 'react'; // 组件内部替换原newCount定义 const newCount = useRef(getData().length); const createNewRowData = () => { const newData = { id: newCount.current, firstName: '', lastName: '' }; newCount.current++; return newData; }
4. 优化isLastRow判断逻辑
使用AgGrid提供的props.node.lastChild直接判断是否为最后一行,更可靠:
export default (props) => { const isLastRow = props.node.lastChild; const addItems = () => { props.addItems(props.rowIndex, props); } return ( <span> {isLastRow && <button onClick={addItems}>Add</button>} {/* 优化Remove按钮,直接删除当前行(可选) */} <button onClick={() => props.api.applyTransaction({remove: [props.data]})}>Remove</button> </span> ); };
内容的提问来源于stack exchange,提问作者copenndthagen
相关产品推荐
相关产品推荐

