Octavian Niculescu
Octavian Niculescu

Reputation: 1327

My cell renderer does not have any data because of an async call

So I have a component which uses a CellRenderer which gets some data:

import { useEffect, useMemo, useState } from "react";

import "ag-grid-community/dist/styles/ag-grid.min.css";
import "ag-grid-community/dist/styles/ag-theme-material.min.css";
import Grid from "../Common/Grid";
import axios from "axios";
import SelectJudetCellRenderer from "./SelectJudetCellRenderer";

function GetJudete() {
  return axios
    .get("http://localhost:5266/api/judete")
    .then((response) => {
      let data = response.data;
      return data;
    })
    .catch((err) => {
      console.log("Eroare la aducerea datelor.");
    });
}

function Localitati() {
  let [judete, setJudete] = useState([]);

  useEffect(() => {
    async function GetJudeteAsync() {
      const result = await GetJudete();
      setJudete(result);
    }
    GetJudeteAsync();
  }, []);

  const [columnDefs] = useState([
    { field: "nume", filter: "agTextColumnFilter", editable: true },
    { field: "judet", filter: "agTextColumnFilter", editable: true, cellRenderer: SelectJudetCellRenderer, cellRendererParams: {judete: judete} },
  ]);
  return (
    <Grid
      baseLink="http://localhost:5266/api/localitati"
      columnDefs={columnDefs}
    />
  );
}

export default Localitati;

Here's my Cell renderer:

import { ICellRendererParams } from 'ag-grid-community';

export interface JudeteCellRendererParams extends ICellRendererParams {
    judete: any[];
}

function SelectJudetCellRenderer(props: JudeteCellRendererParams) {
    console.log(props.judete)
    return (
    <select name="judete">
    {
        props.judete.map((judet) => 
            <option value={judet.id}>{judet.name}</option>
        )
    }
  </select>
  )
}

export default SelectJudetCellRenderer;

The problem is that after the Async call Judete is getting new data but my cell renderer does not get the new data.

The console.log() from the CellRenderer returns an empty array.

Why is this happening and how can I fix it?

Thanks.

Upvotes: 1

Views: 2566

Answers (1)

andrei_f
andrei_f

Reputation: 198

You need to tell AG Grid to refresh the rendered cell, this is not very well documented, see https://www.ag-grid.com/javascript-data-grid/component-cell-renderer/#cell-renderer-component

Here is a simple example using Angular (should be similar for class based React)

Notice the refresh() method:

  // gets called whenever the user gets the cell to refresh
  refresh(params: ICellRendererParams) {
    // set value into cell again
    this.cellValue = this.getValueToDisplay(params);
  }

https://plnkr.co/edit/yFqQHfNjxMLrPb9f.

For functional components you should explicitly call the api.refreshCells() when the data is available.
See here for more details: https://www.ag-grid.com/react-data-grid/component-cell-renderer/#component-refresh

A possible solution (although I think it would be more simple to switch to a class component renderer)

 function Localitati() {
  let [judete, setJudete] = useState([]);

  // get hold of AG Grid gridApi
  const gridApiRef = React.useRef<GridApi>();

  // update the 'judete' column when new data is available (this will re-invoke the cell renderers)
  useEffect(() => {
    gridApiRef.current.refreshCells({columns: 'judet'});
  }, [judete]);

  useEffect(() => {
    async function GetJudeteAsync() {
      const result = await GetJudete();
      setJudete(result);
    }
    GetJudeteAsync();
  }, []);

  const [columnDefs] = useState([
    { field: "nume", filter: "agTextColumnFilter", editable: true },
    { field: "judet", filter: "agTextColumnFilter", editable: true, cellRenderer: SelectJudetCellRenderer, cellRendererParams: {judete: judete} },
  ]);
  return (
    <Grid
      baseLink="http://localhost:5266/api/localitati"
      columnDefs={columnDefs}
      onGridReady={({ api }) => {
        gridApiRef.current = api;
      }}
    />
  );
}

Upvotes: 1

Related Questions