ag-Grid React dimentica gridApi dopo che è stato impostato
Ho modificato l' esempio Selection with Keys per lavorare con React. Tuttavia, non appena premo un tasto freccia, l'app si arresta in modo anomalo nel codice seguente:
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!');
}
...
};
Sto impostando l' gridApiuso onGridReadyprima di premere qualsiasi tasto (confermato aggiungendo a console.log). Quindi non so come stia andando undefined.
Il mio codice sorgente completo è qui .
Risposte
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!");
}
...
}
Questo è comunemente noto come chiusura stantia nel reagire hook. Dalla mia comprensione ecco cosa succede:
- La tua richiamata
keyboardNavigationviene registrata solo una volta al primo rendering. keyboardNavigationin quel momento fa riferimentogridApiall'istanza dal primo rendering che èundefined.AgGridReactnei successivi ri-rendering utilizzerà la primakeyboardNavigationistanza, quindi fa riferimento allo stesso vecchiogridApianche se è stato impostato ora.
Puoi verificare che accedendo al gridApimetodo render, puoi vedere dal secondo rendering, che è stato inizializzato mentre la tua chiusura fa keyboardNavigation ancora riferimento all'istanza non aggiornata di gridApi.
Per risolvere questo problema, puoi modificare il codice sopra per utilizzare il riferimento invece della variabile che non può essere modificata una volta cotta nella chiusura.
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()
}
Dimostrazione dal vivo