Reactjs ag Grid React在设置gridApi后会忘记它

Reactjs ag Grid React在设置gridApi后会忘记它,reactjs,ag-grid,ag-grid-react,Reactjs,Ag Grid,Ag Grid React,我已经修改了该示例以使用React。但是,只要我按下箭头键,应用程序就会崩溃,代码如下: const[gridApi,setGridApi]=useState; const handleGridReady=事件:GridReadyEvent=>{ setGridApievent.api; setGridColumnApievent.columnApi; }; const keyboardNavigation=params:NavigateToNextCellParams:CellPosition

我已经修改了该示例以使用React。但是,只要我按下箭头键,应用程序就会崩溃,代码如下:

const[gridApi,setGridApi]=useState; const handleGridReady=事件:GridReadyEvent=>{ setGridApievent.api; setGridColumnApievent.columnApi; }; const keyboardNavigation=params:NavigateToNextCellParams:CellPosition=>{ 如果gridApi==未定义{ 抛出新错误“这永远不会发生!”; } ... }; 我正在使用onGridReady设置gridApi,然后通过添加console.log确认按下任何键。所以我不知道它是如何变得不明确的

我的完整源代码是。

const[gridApi,setGridApi]=React.useState; const onGridReady=params:GridReadyEvent=>{ setGridApiparams.api; setGridColumnApiparams.columnApi; }; console.loggridApi;//如果重新渲染,则记录最新的gridApi实例 常量键盘导航= 参数:NavigateToNextCellParams :CellPosition=>{ //始终引用gridApi的第一个实例 如果gridApi==未定义{ 抛出新错误这应该总是发生!; } ... } 这通常被称为react hook中的stale闭包。根据我的理解,发生了以下情况:

回调键盘导航在第一次渲染时仅注册一次。 当时的键盘导航引用了第一次渲染时未定义的gridApi实例。 AgGridReact在随后的重新渲染中将使用第一个keyboardNavigation实例,因此即使现在已经设置了gridApi,也会引用它。 您可以通过在render方法中记录gridApi来验证,您可以从第二次渲染中看到,它已经初始化,而闭包键盘导航仍然引用gridApi的陈旧实例

要解决这个问题,您可以将上面的代码更改为使用引用,而不是在闭包中烘焙后无法更改的变量

类型AgGridApi={ grid?:GridApi; column?:ColumnApi; }; ... const apiRef=React.useRef

const[gridApi,setGridApi]=React.useState; const onGridReady=params:GridReadyEvent=>{ setGridApiparams.api; setGridColumnApiparams.columnApi; }; console.loggridApi;//如果重新渲染,则记录最新的gridApi实例 常量键盘导航= 参数:NavigateToNextCellParams :CellPosition=>{ //始终引用gridApi的第一个实例 如果gridApi==未定义{ 抛出新错误这应该总是发生!; } ... } 这通常被称为react hook中的stale闭包。根据我的理解,发生了以下情况:

回调键盘导航在第一次渲染时仅注册一次。 当时的键盘导航引用了第一次渲染时未定义的gridApi实例。 AgGridReact在随后的重新渲染中将使用第一个keyboardNavigation实例,因此即使现在已经设置了gridApi,也会引用它。 您可以通过在render方法中记录gridApi来验证,您可以从第二次渲染中看到,它已经初始化,而闭包键盘导航仍然引用gridApi的陈旧实例

要解决这个问题,您可以将上面的代码更改为使用引用,而不是在闭包中烘焙后无法更改的变量

类型AgGridApi={ grid?:GridApi; column?:ColumnApi; }; ...
const apiRef=React.useRef

哇,我怎么也猜不到这个!非常感谢你,亲爱的。我实现了一个使用两个useRef而不是一个的小变化:const gridApiRef=useRef;const columnApiRef=useRef;这样我就不必为这两个API创建新类型,也可以避免嵌套引用。这个主意来自于。@Naresh不客气。陈旧的闭包是react钩子中常见的陷阱之一,尤其是当您从基于类的组件切换到功能组件并开始使用钩子时。拥有一个好的心智模型将帮助你更快地发现问题。你可以通过阅读更多关于这个案例中引擎盖下的工作原理来做到这一点。哇,我从来没有猜到这个!非常感谢你,亲爱的。我实现了一个使用两个useRef而不是一个的小变化:const gridApiRef=useRef;const columnApiRef=useRef;这样我就不必为这两个API创建新类型,也可以避免嵌套引用。这个主意来自于。@Naresh不客气。陈旧的闭包是react钩子中常见的陷阱之一,尤其是当您从基于类的组件切换到功能组件并开始使用钩子时。拥有一个好的心智模型将帮助你更快地发现问题。在本例中,您可以通过阅读更多关于发动机罩下的工作原理来实现这一点。