ag-Grid React vergisst gridApi, nachdem es eingestellt wurde
Ich habe das Beispiel Auswahl mit Schlüsseln geändert , um mit Reagieren zu arbeiten. Sobald ich jedoch eine Pfeiltaste drücke, stürzt die App im folgenden Code ab:
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!');
}
...
};
Ich stelle gridApimit ein, onGridReadybevor Tasten gedrückt werden (bestätigt durch Hinzufügen von a console.log). Ich weiß also nicht, wie es wird undefined.
Mein vollständiger Quellcode ist hier .
Antworten
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!");
}
...
}
Dies ist allgemein als abgestandener Verschluss im Reaktionshaken bekannt. Nach meinem Verständnis passiert hier Folgendes:
- Ihr Rückruf
keyboardNavigationwird beim ersten Rendern nur einmal registriert. keyboardNavigationZu diesem Zeitpunkt wird auf diegridApiInstanz vom ersten Rendering verwiesenundefined.AgGridReactBei nachfolgenden erneuten Rendern wird die erstekeyboardNavigationInstanz verwendet, sodass auf dieselbe alte Instanz verwiesen wird,gridApiauch wenn sie jetzt festgelegt wurde.
Sie können überprüfen, ob durch Protokollieren der gridApiRender-Methode, die Sie beim zweiten Rendern sehen können, diese initialisiert wurde, während Ihr Abschluss keyboardNavigation weiterhin auf die veraltete Instanz von verweist gridApi.
Um dies zu beheben, können Sie den obigen Code so ändern, dass anstelle der Variablen eine Referenz verwendet wird, die nach dem Backen im Closure nicht mehr geändert werden kann.
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()
}
Live-Demo