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

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>
        );
};

问题原因

  1. Cell Renderer未自动刷新:AgGrid的单元格渲染器默认不会因行顺序变化重新渲染,添加新行后原行的isLastRow判断未更新。
  2. 状态更新逻辑错误:setGridData(...gridData, res.add[0].data)错误地将数组拆分为多个参数传递,未正确更新gridData状态。
  3. 变量作用域问题:newCount定义在组件函数内部,每次组件渲染都会重置,导致新增行ID计算错误。
  4. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 01:24:13