最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - AG-Grid React, trouble getting custom cell renderer to update when data changes. Function components are behaving d

programmeradmin3浏览0评论

I'm using AG-Grid throughout a react application, and in several instances I want a cellRenderer to update when grid data changes. In both of the following cases, the cellRenderer loads correctly initially, but doesn't update when data changes:

  1. A user edits an editable cell and changes the value.
  2. The server updates the grid data in redux

Check out this codesandbox

In this example I recreated the first use case with an editable cell, and used a class ponent and a function ponent. Using onCellValueChanged with params.api.refreshCells() I was able to get the class ponent to update, but not the function ponent.

First question: How do I get react function ponents to re-render with new props, the same way the class ponent re-renders in the codesandbox example?

Second question: Is there a better way to update a cellRenderer without un-mounting and re-mounting every cell in the column any time data updates?

Thanks in advance for the help and guidance!

...
    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;

I'm using AG-Grid throughout a react application, and in several instances I want a cellRenderer to update when grid data changes. In both of the following cases, the cellRenderer loads correctly initially, but doesn't update when data changes:

  1. A user edits an editable cell and changes the value.
  2. The server updates the grid data in redux

Check out this codesandbox

In this example I recreated the first use case with an editable cell, and used a class ponent and a function ponent. Using onCellValueChanged with params.api.refreshCells() I was able to get the class ponent to update, but not the function ponent.

First question: How do I get react function ponents to re-render with new props, the same way the class ponent re-renders in the codesandbox example?

Second question: Is there a better way to update a cellRenderer without un-mounting and re-mounting every cell in the column any time data updates?

Thanks in advance for the help and guidance!

...
    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;
Share Improve this question asked May 14, 2020 at 21:28 M WellmanM Wellman 731 gold badge1 silver badge5 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

1.Cell Renderer Function

A cell renderer function should be used when you dont have refresh requirements and this is mentioned in the ag-grid docs.

As per docs-

Use the function variant of a cell renderer if you have no refresh or cleanup requirements (ie you don't need to implement the refresh or destroy functions).

This is the reason why your cell renderer function does not refresh.

To solve your problem, you can do this -

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

2.Cell Renderer Component

The reason your GridCellClass works on api.refreshCells() is because the grid handles the refresh() for you since you have not implemented refresh() in your GridCellClass ponent.

What that means is your ponent will be destroyed and recreated if the underlying data changes.

3.RefreshCells

Also note that using api.refreshCells() won't work as is because ag-grid uses change detection to refresh cells while determining what cells to refresh and since essentially the value of your other 2 columns do not change but infact they are changed in the cellRenderer itself.

However the below works for GridCellClass because you disable change detection by passing force:true,

       params.api.refreshCells({
          force: true
        });

From docs-

Change detection will be used to refresh only cells who's display cell values are out of sync with the actual value. If using a cellRenderer with a refresh method, the refresh method will get called.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论