TL;DR
Utilize useState or useRef hooks and gridReady event to maintain access to Grid API and Column API. Check here for code samples.
AG-GRID IN REACT 16.8.0+
ag-Grid has an impressive set of features, matched by unusually comprehensive documentation. The issue is that at this moment (February 2020), most of the React-specific examples are written for class components. Because of this, using the grid inside a function (functional) component could be slightly challenging. One of the things that are not so obvious is how to access Grid API and Column API...
Grid and Column APIs have over 150 methods that let you manipulate everything from cell focus to column width. The docs suggest obtaining and saving references to these APIs inside gridReady event handler:
class GridExample extends Component {
// Irrelevant parts removed for brevity...
onGridReady = params => {
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
}
render() {
return (
<AgGridReact
onGridReady={this.onGridReady}
/>
);
}
}
Such approach works nicely in a class component but doesn't work when component is "just" a function. Worry not! useState and useRef hooks (part of React 16.8.0) can help you access the APIs in a function component and it's all quite easy!
I've asked ag-Grid team if they have a preference between useState and useRef and they don't, so I will show you the two options and you can pick the one that suites you.
Here's a component that uses selectAll method from Grid API and moveColumnByIndex method from Column API with the help of useState hook:
import React, { useState } from "react";
import { AgGridReact } from "ag-grid-react";
import { columnDefs } from "./columnDefs";
import { rowData } from "./rowData";
import "ag-grid-community/dist/styles/ag-grid.css";
import "ag-grid-community/dist/styles/ag-theme-balham.css";
const AgGridWithUseState = () => {
console.log("AgGridWithUseState Render");
const [gridApi, setGridApi] = useState();
const [columnApi, setColumnApi] = useState();
return (
<div className="example">
<h1>API access with useState</h1>
<div>
<button
onClick={() => gridApi && gridApi.selectAll()}>
Grid API selectAll()
</button>
<button
onClick={() => columnApi && columnApi.moveColumnByIndex(0, 1)}>
Column API moveColumnByIndex(0, 1)
</button>
</div>
<div className="ag-theme-balham">
<AgGridReact
columnDefs={columnDefs}
rowData={rowData}
rowSelection="multiple"
onGridReady={params => {
console.log("AgGridWithUseState Grid Ready");
setGridApi(params.api);
setColumnApi(params.columnApi);
}}
/>
</div>
</div>
);
};
export default AgGridWithUseState;
and below is the exact same thing done with useRef:
import React, { useRef } from "react";
import { AgGridReact } from "ag-grid-react";
import { columnDefs } from "./columnDefs";
import { rowData } from "./rowData";
import "ag-grid-community/dist/styles/ag-grid.css";
import "ag-grid-community/dist/styles/ag-theme-balham.css";
const AgGridWithUseRef = () => {
console.log("AgGridWithUseRef Render");
const gridApi = useRef();
const columnApi = useRef();
return (
<div className="example">
<h1>API access with useRef</h1>
<div>
<button
onClick={() => gridApi.current && gridApi.current.selectAll()}>
Grid API selectAll()
</button>
<button
onClick={() => columnApi.current && columnApi.current.moveColumnByIndex(0, 1)}>
Column API moveColumnByIndex(0, 1)
</button>
</div>
<div className="ag-theme-balham">
<AgGridReact
columnDefs={columnDefs}
rowData={rowData}
rowSelection="multiple"
onGridReady={params => {
console.log("AgGridWithUseRef Grid Ready");
gridApi.current = params.api;
columnApi.current = params.columnApi;
}}
/>
</div>
</div>
);
};
export default AgGridWithUseRef;
Check the function assigned to onGridReady property to find out how to retrieve and keep references to the APIs. Button's onClick handlers show you how to use the APIs.
USEREF VS USESTATE (DEMO)
Live demo: https://morzel85.github.io/blog-post-ag-grid-api-access-with-hooks
Source code on GitHub: https://github.com/morzel85/blog-post-ag-grid-api-access-with-hooks
The app uses React 16.12.0 and ag-Grid Community 22.1.1 (I've tested it in Chrome 80, Firefox 73, Edge 44).
Clone the repo, do npm install and npm start to run the app locally (just like with any other thing started with create-react-app)...
Demo shows access to selectAll method from Grid API and moveColumnByIndex method from Column API. This application has two grids that differ only in the way the APIs are accessed (one uses useState hook, the other goes with useRef hook).
What's the difference between useState and useRef version?
It boils down to the way hooks are designed to work. useState causes component rerender and useRef doesn't. You can see the difference if you open the console and check the log:
Notice two "AgGridWithUseState Render" lines after "AgGridWithUseState Grid Ready".
This happens because Grid and Column APIs are set by two calls to state hook setters and that causes component rerenders. Sounds bad? Remember that in React, a component rerender doesn't necessary mean any DOM change has to be applied. ag-Grid is also smart enough to avoid unnecessary work. useState triggers rendering by design and it lets you write the component in more declarative way. For example you could keep rowData and columnDefs in state and have the grid update itself without explicit API calls...
How about the useRef approach? Use it if you don't need to run any action as a result of API reference being set.