AgGrid React中如何防止自定义ToolPanel重渲染时自动折叠
问题根因
自动折叠的核心原因是写法导致每次重渲染都会给AgGrid传入全新的工具面板配置,AgGrid检测到组件引用变化后会直接销毁旧面板、重建新面板,展开状态自然会丢失,具体问题点有两个:
- 你在
sideBar配置里写的toolPanel: MyToolPanel({selected: selected})是直接执行组件函数拿返回值,不是传组件引用。每次父组件因为selected状态更新重渲染时,这里都会生成一个全新的函数,AgGrid会判定为换了个新工具面板,直接重置状态。 - 自定义ToolPanel组件没有实现AgGrid要求的
refresh方法,参数变化时AgGrid默认会重挂载组件,进一步导致状态丢失。
修复方案
第一步:修正自定义ToolPanel组件写法
不要写两层嵌套的返回函数,直接接收AgGrid传入的参数,同时加refresh静态方法告诉AgGrid组件可自主处理更新,不需要重挂载:
import { IToolPanelParams } from 'ag-grid-community'; const Container = styled.div` margin: 0px auto; padding: 10px; `; // 扩展AgGrid原生工具面板参数类型,加入自定义传参 export interface MyToolPanelParams extends IToolPanelParams { selected: MyRowData[]; } export const MyToolPanel = (params: MyToolPanelParams) => { // 直接从AgGrid传入的params中取动态参数 return ( <Container> <AnotherComponentThatProcessesSelectedItems selected={params.selected} /> </Container> ); }; // 关键:告诉AgGrid组件自己处理刷新逻辑,不需要销毁重建 MyToolPanel.prototype.refresh = () => true;
第二步:固定Grid配置引用,用官方规范传动态参数
所有传给AgGrid的配置项要用useMemo、useCallback包裹保证引用稳定,动态参数通过toolPanelParams字段传递,不要直接修改toolPanel的组件引用:
import { useCallback, useMemo, useState } from 'react'; import { AgGridReact } from 'ag-grid-react'; import { GridOptions } from 'ag-grid-community'; const [selected, setSelected] = useState<MyRowData[]>([]); // 固定选中事件回调引用 const handleSelectionChanged = useCallback((e) => { setSelected(e.api.getSelectedRows()); }, []); // 固定gridOptions引用,仅在依赖变化时更新 const gridOptions = useMemo<GridOptions>(() => ({ onSelectionChanged: handleSelectionChanged, // 其余原有gridOptions配置统一放在这里 }), [handleSelectionChanged]); // 固定侧边栏配置引用,toolPanel直接传组件本身,不要加括号执行 const sideBarConfig = useMemo(() => ({ toolPanels: [ "columns", "filters", { id: 'myToolPanel', labelDefault: 'My Tool Panel', labelKey: 'myToolPanel', iconKey: 'columns', toolPanel: MyToolPanel, // 直接传组件引用,不要提前执行 toolPanelParams: { selected: selected // 动态变化的参数走这个字段传递 } } ] // 仅在selected变化时更新参数,组件引用始终保持不变 }), [selected]); return ( <AgGridReact gridOptions={gridOptions} sideBar={sideBarConfig} /> );
额外兜底方案(极端场景使用)
如果遇到特殊AgGrid版本仍存在状态重置问题,可以主动记忆面板展开状态,Grid就绪后主动恢复:
// 新增状态记录当前展开的面板ID const [openedToolPanel, setOpenedToolPanel] = useState<string | null>(null); const gridOptions = useMemo<GridOptions>(() => ({ onSelectionChanged: handleSelectionChanged, // 监听面板开关状态,实时记录 onToolPanelVisibleChanged: (e) => { if (e.visible) { setOpenedToolPanel(e.key); } else if (openedToolPanel === e.key) { setOpenedToolPanel(null); } }, // Grid加载完成后主动恢复展开状态 onGridReady: (e) => { if (openedToolPanel) { e.api.openToolPanel(openedToolPanel); } // 其余原有onGridReady逻辑放在这里 } }), [handleSelectionChanged, openedToolPanel]);
内容的提问来源于stack exchange,提问作者Ryan Pierce Williams
相关产品推荐
相关产品推荐

