ag-Grid React melupakan gridApi setelah disetel
Saya telah memodifikasi contoh Seleksi dengan Tombol untuk bekerja dengan React. Namun begitu saya menekan tombol panah, aplikasi macet dalam kode di bawah ini:
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!');
}
...
};
Saya menyetel gridApimenggunakan onGridReadysebelum tombol apa pun ditekan (dikonfirmasi dengan menambahkan a console.log). Jadi saya tidak tahu bagaimana hasilnya undefined.
Kode sumber lengkap saya ada di sini .
Jawaban
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!");
}
...
}
Ini umumnya dikenal sebagai penutupan basi dalam kait reaksi. Dari pemahaman saya inilah yang terjadi:
- Callback Anda
keyboardNavigationhanya terdaftar sekali pada render pertama. keyboardNavigationpada saat itu mereferensikangridApiinstance dari render pertama yaituundefined.AgGridReactdalam perenderan ulang berikutnya akan menggunakankeyboardNavigationcontoh pertama , sehingga mereferensikan yang lama samagridApimeskipun telah disetel sekarang.
Anda dapat memverifikasi bahwa dengan masuk ke gridApidalam metode render, Anda dapat melihat dari render kedua, ini telah diinisialisasi sementara closure Anda keyboardNavigationmasih mereferensikan instance basi dari gridApi.
Untuk memperbaikinya, Anda dapat mengubah kode di atas untuk menggunakan referensi, bukan variabel yang tidak dapat diubah setelah dimasukkan dalam closure.
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()
}
Demo Langsung