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

如何在React AG-Grid数据更新时高效自动调整列宽

AG-Grid React 数据更新后高效自动调整列宽方案

问题场景

我有一个使用AG-Grid的React应用,用户通过下拉框选择筛选值后点击'Get Data',应用会请求后端,后端再调用外部API获取对应数据并在前端渲染表格。需求是:每次重新渲染新数据(即每次点击'Get Data')时,高效自动调整列宽以适配内容。

Grid.jsx 原代码

import { AgGridReact } from 'ag-grid-react';
import { useEffect, useState, useMemo, useRef, useCallback } from 'react';

import 'ag-grid-community/styles/ag-grid.css'; // Core grid CSS, always needed
import 'ag-grid-community/styles/ag-theme-alpine.css'; // Optional theme CSS, comment out for custom styling
import './Grid.css';

const Grid = ({ gridData }) => {
    const gridRef = useRef();

    // Columns definition
    const [columnDefs, setColumnDefs] = useState([]);

    // Data/rows definition
    const [rowData, setRowData] = useState([]);

    // Transform grid data into format ag-grid can use
    const transformGridData = () => {
        const { columns, rows, cells } = gridData;
        const transformedColumnDefs = [];
        const transformedRowData = [];
        
        // ...

        // (omitted) A BUNCH OF LOGIC FOR PARSING THE DATA AND CONVERTING IT INTO AG-GRID's COLS AND ROWS
        
        // ...

        // Set column defs and row data
        setColumnDefs(transformedColumnDefs);
        setRowData(transformedRowData);
    }

    // Default column style/functionality definition
    const defaultColDef = useMemo(() => ({
        // default col settings
    }), []);

    // Update the grid when data given by external API changes
    useEffect(() => {
        if (gridData != null) {
            transformGridData();
        }
    }, [gridData]);

    return (
        <div className="ag-theme-alpine grid-div" style={{ height: 600, marginTop: 50, marginLeft: 17 }}>
            <AgGridReact
                ref={gridRef}
                rowData={rowData}
                columnDefs={columnDefs}
                defaultColDef={defaultColDef}
            />
        </div>
    )
}

export default Grid;

已尝试的方法

  • 编写自动调整所有列宽的函数:
    const autoSizeAll = useCallback(() => {
            const allColumnIds = [];
            gridRef.current.columnApi.getColumns().forEach((column) => {
                allColumnIds.push(column.colId);
            });
    
            gridRef.current.columnApi.autoSizeColumns(allColumnIds);
    }, []);
    
  • 通过onFirstDataRendered和onDisplayedColumnsChanged触发该函数,虽生效但应用性能大幅下降;
  • 在transformGridData中设置columnDefs和rowData后直接调用autoSizeAll,结果首次点击仅填充数据不调整列宽,再次点击才生效。

高效解决方案

1. 优化自动列宽函数

只针对可见列执行调整,跳过隐藏列减少计算量,同时做安全校验避免空指针:

const autoSizeAll = useCallback(() => {
  if (!gridRef.current?.columnApi) return;
  // 获取所有可见列的ID,避免处理隐藏列
  const visibleColumnIds = gridRef.current.columnApi.getAllDisplayedColumns().map(column => column.colId);
  // 第二个参数设为false会同时适配表头内容,按需调整
  gridRef.current.columnApi.autoSizeColumns(visibleColumnIds, false);
}, []);

2. 选择精准的触发时机

避免使用触发频繁的onDisplayedColumnsChanged,改用以下两个精准事件:

  • onFirstDataRendered:首次加载数据时触发一次
  • onRowDataChanged:每次rowData更新(即新数据渲染)时触发

在AgGridReact组件中绑定事件:

<AgGridReact
  ref={gridRef}
  rowData={rowData}
  columnDefs={columnDefs}
  defaultColDef={defaultColDef}
  onFirstDataRendered={autoSizeAll}
  onRowDataChanged={autoSizeAll}
/>

3. 可选:防抖优化(针对频繁数据更新场景)

如果数据可能短时间内多次更新,用防抖函数限制自动调整的执行频率,避免性能浪费:

import { debounce } from 'lodash';

const autoSizeAll = useCallback(debounce(() => {
  if (!gridRef.current?.columnApi) return;
  const visibleColumnIds = gridRef.current.columnApi.getAllDisplayedColumns().map(column => column.colId);
  gridRef.current.columnApi.autoSizeColumns(visibleColumnIds, false);
}, 100), []);

方案说明

  • 直接调用不生效的原因:React的setState是异步操作,在transformGridData中设置数据后,网格还未完成新数据加载,此时调用调整函数无法获取新内容的宽度信息。
  • 之前性能下降的原因:onDisplayedColumnsChanged会在列显示/隐藏、列顺序调整等多种场景触发,并非仅在数据更新时,导致调整函数频繁执行。

内容的提问来源于stack exchange,提问作者WesternCreamCheese

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 15:07:23