React AgGrid单条数据时首次加载无法高亮首行问题解决
解决React AgGrid首次插入数据无法高亮首行的问题
问题原因
React的setRowData是异步状态更新,调用后不会立即触发AgGrid的行数据渲染。第一次点击按钮时,你在setRowData后直接调用forEachNode,此时网格还未完成新行的渲染,因此无法获取到行节点;第二次点击时,状态已完成更新,网格已渲染行数据,所以高亮功能正常生效。
解决方案
方案1:使用useEffect监听rowData变化
利用React的useEffect钩子,在rowData更新完成后触发高亮操作,确保网格已经渲染出新行。
修改后的完整代码:
import {AgGridReact} from 'ag-grid-react'; import 'ag-grid-community/dist/styles/ag-grid.css'; import 'ag-grid-community/dist/styles/ag-theme-alpine.css'; import {useState, useRef, useEffect, useCallback} from 'react'; import {createOneCarRecord} from './carFactory'; export const AppHighLightFirstRow = () => { const gridRef = useRef(); const [rowData, setRowData] = useState(null); const gridAPI = useRef(null); // 改用useRef存储gridAPI,避免全局变量污染 const [columnDefs, setColumnDefs] = useState([ { field: 'type', sortable: true }, { field: 'year' }, { field: 'color' }, { field: 'price' } ]); const getRowId = useCallback( params => { return params.data.id; }, []); const onInsertOne = useCallback( ()=> { const newRecord = createOneCarRecord(); setRowData([newRecord]); }, []); const onGridReady = (params) => { params.api.hideOverlay(); gridAPI.current = params.api; }; // 监听rowData变化,更新后高亮首行 useEffect(() => { if (rowData && rowData.length > 0 && gridAPI.current) { const firstRowNode = gridAPI.current.getDisplayedRowAtIndex(0); if (firstRowNode) { gridAPI.current.flashCells({ rowNodes: [firstRowNode], flashDelay: 2000, fadeDelay: 1000 }); } } }, [rowData]); return ( <div className="ag-theme-alpine" style={{height: '100%'}}> <div><button onClick={onInsertOne}>Insert One</button></div> <AgGridReact ref={gridRef} enableCellChangeFlash={true} getRowId={getRowId} rowSelection={'multiple'} rowData={rowData} animateRows={true} columnDefs={columnDefs} onGridReady={onGridReady} /> </div> ); };
方案2:使用AgGrid的onRowDataChanged事件
AgGrid在行数据更新完成后会触发onRowDataChanged事件,我们可以在该事件中执行高亮操作,确保网格已完成行渲染。
修改后的关键代码部分:
export const AppHighLightFirstRow = () => { // ...其他状态和钩子保持不变 const [shouldFlash, setShouldFlash] = useState(false); const onInsertOne = useCallback( ()=> { const newRecord = createOneCarRecord(); setRowData([newRecord]); setShouldFlash(true); // 设置高亮标记 }, []); const onRowDataChanged = useCallback(() => { if (shouldFlash && gridAPI.current) { const firstRowNode = gridAPI.current.getDisplayedRowAtIndex(0); if (firstRowNode) { gridAPI.current.flashCells({ rowNodes: [firstRowNode], flashDelay: 2000, fadeDelay: 1000 }); } setShouldFlash(false); // 重置标记 } }, [shouldFlash]); return ( <div className="ag-theme-alpine" style={{height: '100%'}}> <div><button onClick={onInsertOne}>Insert One</button></div> <AgGridReact ref={gridRef} enableCellChangeFlash={true} getRowId={getRowId} rowSelection={'multiple'} rowData={rowData} animateRows={true} columnDefs={columnDefs} onGridReady={onGridReady} onRowDataChanged={onRowDataChanged} // 添加行数据变化监听 /> </div> ); };
关键优化点
- 替换全局
gridAPI为useRef:避免全局变量导致的组件实例间污染问题,确保每个组件持有独立的网格API引用。 - 等待行渲染完成:两种方案都确保在网格完成新行渲染后再执行高亮,解决了异步更新导致的行节点获取失败问题。
内容的提问来源于stack exchange,提问作者Raj
相关产品推荐
相关产品推荐

