如何在 React 函数组件(useState 挂钩)中访问 ag-Grid API?

Posted

技术标签:

【中文标题】如何在 React 函数组件(useState 挂钩)中访问 ag-Grid API?【英文标题】:How to access ag-Grid API in React function component (useState hook)? 【发布时间】:2020-05-23 17:41:37 【问题描述】:

React 函数 组件中访问 ag-Grid API 的最佳方式是什么?

我必须使用 API 中的一些方法(getSelectedNodessetColumnDefs 等),所以我在 onGridReady 事件处理程序中保存了对 API 的引用(使用 useState 钩子):

onGridReady=params => 
    setGridApi(params.api);

然后我可以像这样调用 API:gridApi.getSelectedNodes()

我没有注意到这种方法有任何问题,但我想知道是否还有更多惯用方法?

堆栈:

ag-grid-community & ag-grid-react 22.1.1 反应 16.12.0

【问题讨论】:

【参考方案1】:

我们找到了使用 ref 最惯用的方式。因为 api 不是我们组件的状态。实际上可以简单地做:

<AgGridReact ref=grid/>

然后与

一起使用
grid.current.api

这里是一个例子:

import React,  useRef  from 'react'
import  AgGridReact  from 'ag-grid-react'
import  AgGridReact as AgGridReactType  from 'ag-grid-react/lib/agGridReact'

const ShopList = () => 
  const grid = useRef<AgGridReactType>(null)

 ...

  return (
    <AgGridReact ref=grid columnDefs=columnDefs rowData=shops />
  )


这里的好处是,您可以访问 gridApi,但也可以访问 columnApi。就像这样:

// rendering menu to show/hide columns:
columnDefs.map(columnDef =>
  <>
    <input
    type='checkbox'
    checked=
        grid.current
        ? grid.current.columnApi.getColumn(columnDef.field).isVisible()
        : !(columnDef as  hide: boolean ).hide
    
    onChange=() => 
        if (grid.current?.api) 
        const col = grid.current.columnApi.getColumn(columnDef.field)
        grid.current.columnApi.setColumnVisible(columnDef.field, !col.isVisible())
        grid.current.api.sizeColumnsToFit()
        setForceUpdate(x => ++x)
        
    
    />
    <span>columnDef.headerName</span>
  </>
)

【讨论】:

这应该是新接受的答案。最好符合官方文档。 作为建议,您可能需要在 const grid = useRef&lt;AgGridReactType&gt;(null) 行上方添加 // prettier-ignore 以防止在 VS Code 中自动格式化它。 很好的答案。它为打字稿用户提供了一种他们可以使用的类型,而不是any。但只是想知道,为什么这个奇怪的导入import AgGridReact as AgGridReactType from 'ag-grid-react/lib/agGridReact'?您能否将我指向使用/说明的官方文档。我原以为这是一个“***”模块,就像深入到另一个模块的lib 一样。 我现在不能肯定地告诉你,但我认为该类型要么没有暴露在顶层,要么暴露了同名的类型,但打字略有错误。 在现代 ts 4.X 中你实际上需要import type AgGridReact as AgGridReactType from 'ag-grid-react/lib/agGridReact';【参考方案2】:

嗯,我正在我的项目中这样做。你可以使用useRef钩子来存储gridApi

const gridApi = useRef();

const onGridReady = params => 

   gridApi.current = params.api;  // <== this is how you save it

   const datasource = getServerDataSource(
     gridApi.current,
     
       size: AppConstants.PAGE_SIZE,
       url: baseUrl,
       defaultFilter: props.defaultFilter
     
   );

  gridApi.current.setServerSideDatasource(datasource); // <== this is how you use it
;

【讨论】:

这似乎也是可行的选择!我希望 ag-Grid 团队的某个人在 SE 上观察 ag-grid 标签并提供权威答案...:/ @user1068352 是的,我也是。我对我的 SE 帐户上的功能组件 agGrid 也有几个问题。如果对您有帮助,请您投票并接受答案:) 我会尝试联系ag团队以获得官方推荐。如果它与 useRef 匹配,我肯定会接受你的回答。记得给问题点赞 ;)【参考方案3】:

我遇到了同样的问题,但这里有一个解决方法,至少可以让您选择选定的行。基本上我正在做的是将 api 从 agGrid 回调发送到另一个函数。具体来说,我使用 OnSelectionChanged 回调来获取当前行节点。示例如下:

  const onSelectionChanged = params => 
    setDetails(params.api.getSelectedRows());
  ;

return (<AgGridReact
          columnDefs=agData.columnDefs
          rowSelection='single'
          enableCellTextSelection=true
          defaultColDef=
            resizable: true,
          
          rowHeight=50
          rowData=agData.rowData
          onCellFocused=function(params) 
            if (params.rowIndex != null) 
              let nNode = params.api.getDisplayedRowAtIndex(params.rowIndex);
              nNode.setSelected(true, true);
            
          
          onSelectionChanged=function(params) 
            onSelectionChanged(params);
            params.api.sizeColumnsToFit();
          
          onGridReady=function(params) 
            let gridApi = params.api;
            gridApi.sizeColumnsToFit();
          
          deltaRowDataMode=true
          getRowNodeId=function(data) 
            return data.id;
          
        />);

【讨论】:

我希望能够持久访问 API - 我什至尝试将 api 挂钩到组件状态,但它似乎失去了原始网格实例的范围......它似乎创建了新实例与初始网格 API 无关。仅供参考,我将 React Boilerplate 与 Redux、Sagas、Reselect 等一起使用。 你试过useState钩子吗?它对我来说很好。【参考方案4】:

只是想知道,为什么需要使用 state-hook,因为 gridApi 在生命周期内不会改变。

如果您检查 ag-grid 团队示例,您会发现他们只使用属性绑定:

onGridReady = params => 
    this.gridApi = params.api;
    this.gridColumnApi = params.columnApi;
;

所以我想,您不需要使用state 来存储API 引用。

【讨论】:

您能否指出您提到的在函数(功能)组件(不是基于类的组件)中使用 this.gridApi 的 ag-grid 团队示例? 从文档中挑选任何东西(并在组合框中选择 ReactJS)just an example 这些是基于类的示例。我的问题明确是关于功能组件的。 请注意,所有示例目前都是用类编写的,例如:class GridExample extends Component @user1068352 抱歉没有明白你在找什么

以上是关于如何在 React 函数组件(useState 挂钩)中访问 ag-Grid API?的主要内容,如果未能解决你的问题,请参考以下文章

React useState() 使用指南

在 React 中,如何使用 hook useState 来设置数据?

React Hooks --- useState 和 useEffect

如何在另一个带有 props 的组件中使用 useState 函数?

使用 useState 在 React 组件之间传递值

react hook介绍