ag-Grid React 在设置后忘记了 gridApi
ag-Grid React forgets gridApi after it has been set
我修改了 Selection with Keys 示例以使用 React。但是,一旦我按下箭头键,应用程序就会在以下代码中崩溃:
const [gridApi, setGridApi] = useState<GridApi | undefined>();
const handleGridReady = (event: GridReadyEvent) => {
setGridApi(event.api);
setGridColumnApi(event.columnApi);
};
const keyboardNavigation = (params: NavigateToNextCellParams): CellPosition => {
if (gridApi === undefined) {
throw new Error('This should never happen!');
}
...
};
我在按下任何键之前使用 onGridReady
设置 gridApi
(通过添加 console.log
确认)。所以我不知道它是如何变得 undefined
.
我的完整源代码是 here。
const [gridApi, setGridApi] = React.useState<GridApi | undefined>();
const onGridReady = (params: GridReadyEvent) => {
setGridApi(params.api);
setGridColumnApi(params.columnApi);
};
console.log(gridApi); // log the latest gridApi instance if re-render
const keyboardNavigation = (
params: NavigateToNextCellParams
): CellPosition => {
// always reference the first instance of gridApi
if (gridApi === undefined) {
throw new Error("This should always happen!");
}
...
}
这在 React Hook 中通常称为 stale closure。根据我的理解,这里发生了什么:
- 您的回调
keyboardNavigation
仅在第一次渲染时注册一次。
当时 keyboardNavigation
从第一个渲染中引用 gridApi
实例,即 undefined
.
AgGridReact
在随后的 re-renders 中将使用第一个 keyboardNavigation
实例,因此引用 the same old gridApi
即使现在已设置。
您可以通过在渲染方法中记录 gridApi
来验证,您可以从第二个渲染中看到,它已经在您的 closure keyboardNavigation
仍然引用 gridApi
.
的 stale 实例
要解决这个问题,您可以更改上面的代码以使用引用而不是变量,变量一旦在闭包中烘焙就无法更改。
type AgGridApi = {
grid?: GridApi;
column?: ColumnApi;
};
...
const apiRef = React.useRef<AgGridApi>({
grid: undefined,
column: undefined
});
const api = apiRef.current;
const onGridReady = (params: GridReadyEvent) => {
apiRef.current.grid = params.api;
apiRef.current.column = params.columnApi;
};
const yourCallback = () => {
api.grid?.doSomething()
api.column?.doSomething()
}
现场演示
我修改了 Selection with Keys 示例以使用 React。但是,一旦我按下箭头键,应用程序就会在以下代码中崩溃:
const [gridApi, setGridApi] = useState<GridApi | undefined>();
const handleGridReady = (event: GridReadyEvent) => {
setGridApi(event.api);
setGridColumnApi(event.columnApi);
};
const keyboardNavigation = (params: NavigateToNextCellParams): CellPosition => {
if (gridApi === undefined) {
throw new Error('This should never happen!');
}
...
};
我在按下任何键之前使用 onGridReady
设置 gridApi
(通过添加 console.log
确认)。所以我不知道它是如何变得 undefined
.
我的完整源代码是 here。
const [gridApi, setGridApi] = React.useState<GridApi | undefined>();
const onGridReady = (params: GridReadyEvent) => {
setGridApi(params.api);
setGridColumnApi(params.columnApi);
};
console.log(gridApi); // log the latest gridApi instance if re-render
const keyboardNavigation = (
params: NavigateToNextCellParams
): CellPosition => {
// always reference the first instance of gridApi
if (gridApi === undefined) {
throw new Error("This should always happen!");
}
...
}
这在 React Hook 中通常称为 stale closure。根据我的理解,这里发生了什么:
- 您的回调
keyboardNavigation
仅在第一次渲染时注册一次。
当时 keyboardNavigation
从第一个渲染中引用gridApi
实例,即undefined
.AgGridReact
在随后的 re-renders 中将使用第一个keyboardNavigation
实例,因此引用 the same oldgridApi
即使现在已设置。
您可以通过在渲染方法中记录 gridApi
来验证,您可以从第二个渲染中看到,它已经在您的 closure keyboardNavigation
仍然引用 gridApi
.
要解决这个问题,您可以更改上面的代码以使用引用而不是变量,变量一旦在闭包中烘焙就无法更改。
type AgGridApi = {
grid?: GridApi;
column?: ColumnApi;
};
...
const apiRef = React.useRef<AgGridApi>({
grid: undefined,
column: undefined
});
const api = apiRef.current;
const onGridReady = (params: GridReadyEvent) => {
apiRef.current.grid = params.api;
apiRef.current.column = params.columnApi;
};
const yourCallback = () => {
api.grid?.doSomething()
api.column?.doSomething()
}