ag-Grid Reactは、設定後にgridApiを忘れます

Sep 25 2020

Reactで動作するように、Selection withKeysの例を変更しました。ただし、矢印キーを押すとすぐに、以下のコードでアプリがクラッシュします。

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!');
    }
    ...
};

キーを押す前にgridApiを使用して設定しonGridReadyています(を追加して確認console.log)。だから私はそれがどのようになっているのか分かりませんundefined。

私の完全なソースコードはここにあります。

回答

2 NearHuscarl Sep 26 2020 at 04:43
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フックの古いクロージャとして知られています。私の理解から、ここで何が起こるかです:

  • コールバックkeyboardNavigationは、最初のレンダリングで1回だけ登録されます。
  • keyboardNavigationその時点で、gridApi最初のレンダリングからインスタンスを参照しますundefined。
  • AgGridReact以降の再レンダリングでは、最初のkeyboardNavigationインスタンスが使用されるため、現在設定されている場合でも同じ古い インスタンスを参照しますgridApi。

あなたはログインしていることを確認することができますgridApirenderメソッドでは、あなたがレンダリング秒から見ることができますが、それは初期化されている閉鎖は 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()
}

ライブデモ