AG-Grid React,无法在数据更改时更新自定义单元格渲染器。函数组件的行为与类组件不同

Posted

技术标签:

【中文标题】AG-Grid React,无法在数据更改时更新自定义单元格渲染器。函数组件的行为与类组件不同【英文标题】:AG-Grid React, trouble getting custom cell renderer to update when data changes. Function components are behaving differently than class components 【发布时间】:2020-08-31 14:22:39 【问题描述】:

我在整个 React 应用程序中使用 AG-Grid,在某些情况下,我希望 cellRenderer 在网格数据更改时更新。在以下两种情况下,cellRenderer 最初都会正确加载,但不会在数据更改时更新:

    用户编辑可编辑单元格并更改值。 服务器更新 redux 中的网格数据

看看这个codesandbox

在这个例子中,我用一个可编辑的单元格重新创建了第一个用例,并使用了一个类组件和一个函数组件。使用 onCellValueChanged 和 params.api.refreshCells() 我能够更新类组件,但不能更新函数组件。

第一个问题:如何让 react 函数组件使用新的 props 重新渲染,就像代码框示例中类组件重新渲染的方式一样?

第二个问题:有没有更好的方法来更新 cellRenderer,而无需在数据更新时卸载和重新安装列中的每个单元格?

提前感谢您的帮助和指导!

...
    this.state = 
      columnDefs: [
        
          headerName: "Editable Country",
          editable: true,
          field: "country",
          width: 200
        ,
        
          headerName: "Class Render",
          cellRendererFramework: GridCellClass,
          colId: "class-renderer",
          width: 200
        ,
        
          headerName: "Function Render",
          cellRendererFramework: GridCellFunction,
          colId: "function-renderer",
          width: 200
        
      ],
      rowData: []
    ;
  

...

            <AgGridReact
              rowModelType="infinite"
              columnDefs=this.state.columnDefs
              enableColResize=true
              rowClassRules=
                california: function(params) 
                  return params.data.country === "California";
                
              
              onCellValueChanged=function(params) 
                return params.api.refreshCells(
                  force: true,
                  columns: ["class-renderer", "function-renderer"]
                );
              
              onGridReady=this.onGridReady.bind(this)
              rowData=this.state.rowData
            />
...
// This one updates!
import React,  Component  from "react";

class GridCellClass extends Component 
  constructor(props) 
    super(props);
    this.state = ;
  

  render() 
    const  data  = this.props;

    return (
      <div>
        data.country === "California" ? "CALIFORNIA!!!" : "Not California"
      </div>
    );
  


export default GridCellClass;
// This one does not update.
import React from "react";

function GridCellFunction(props) 
  const  data  = props;

  return (
    <div>
      data.country === "California" ? "CALIFORNIA!!!" : "Not California"
    </div>
  );


export default GridCellFunction;

【问题讨论】:

【参考方案1】:

1.单元格渲染函数

当您没有刷新要求时应使用单元格渲染器功能,这在 ag-grid 文档中有所提及。

根据docs-

如果您没有刷新,请使用单元格渲染器的函数变体或 清理要求(即您不需要实现刷新或 销毁函数)。

这就是您的单元格渲染器功能不刷新的原因。

要解决你的问题,你可以这样做 -

      onCellValueChanged=function(params) 
        if(params.column.getId() === 'country') 
          params.api.redrawRows();
        
      

2.单元格渲染器组件

GridCellClassapi.refreshCells() 上起作用的原因是网格为您处理了refresh(),因为您尚未在GridCellClass 组件中实现refresh()

这意味着如果基础数据发生更改,您的组件将被销毁并重新创建。

3.刷新单元格

还请注意,使用 api.refreshCells() 将无法按原样工作,因为 ag-grid 使用更改检测来刷新单元格,同时确定要刷新哪些单元格,因为本质上您的其他 2 列的值不会改变,但实际上它们已更改在 cellRenderer 本身中。

但是,以下内容适用于 GridCellClass,因为您通过传递 force:true 禁用更改检测,

       params.api.refreshCells(
          force: true
        );

来自文档-

更改检测将用于仅刷新显示单元格的单元格 值与实际值不同步。如果使用 cellRenderer 使用 refresh 方法时,会调用 refresh 方法。

【讨论】:

redrawRows 适用于两者,这很棒。在 GridCellClass 中添加刷新方法似乎是一个更好的主意,不会导致不必要的重新挂载。我找到了在类组件中使用刷新方法的示例,但找不到任何用于函数组件的方法。你知道这是否支持? 我在答案和文档中提到的函数不支持刷新 - 如果您没有刷新或清理要求(即您不需要),请使用单元格渲染器的函数变体实现刷新或销毁功能)。 知道了。如果我想在单元格渲染器组件中使用反应钩子,我可以看到这是一个问题,该组件需要是一个函数而不是一个类。它仍然是一个反应组件,而不是一个“简单的功能”。文档说它需要 getGui()

以上是关于AG-Grid React,无法在数据更改时更新自定义单元格渲染器。函数组件的行为与类组件不同的主要内容,如果未能解决你的问题,请参考以下文章

使用 React 加载新表后使用新数据更新 ag-grid

如何使用 ag-grid 的布尔数据复选框

React 中的 Ag-grid 纯 JS 单元格渲染器

如何在我的 ag-grid 单元格中放置一个 react jsx 组件

在 ag-grid 中使用自定义单元格渲染器时无法读取未定义的属性“导航”

react 关于ag-grid自定义pin