【问题标题】:How to access ag-Grid API in React function component (useState hook)?如何在 React 函数组件(useState 挂钩)中访问 ag-Grid API?
【发布时间】: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

【问题讨论】:

    标签: function react-hooks ag-grid ag-grid-react


    【解决方案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 抱歉没有明白你在找什么
    猜你喜欢
    • 1970-01-01
    • 2019-10-28
    • 2020-04-29
    • 2019-06-06
    • 2021-05-16
    • 2021-02-19
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    相关资源
    最近更新 更多