2

I have a table ( Grid ) using AGGRID ( react-grid ) It works very well except that I want to INVALIDATE the table

The issue is I am not able to use useQuery inside onGridReady

so I only use fetch to get the data, BUT here I lose react-query functionality like caching and invalidation .

Here is the table component

export const WorkspaceSpacesTable = () => {
  const { workspaceId } = useParams();
  const { theme } = useThemeStore();
  const [searchParam, setSearchParam] = useState('');
  const navigate = useNavigate();

  const setGridApi = useSpacesGrid((state) => state.setGridApi);

  const defaultColDef = {
    filter: true,
    sortable: true,
    resizable: true,
  };

  const [colDefs] = useState<ColDef[]>([
    {
      field: 'name',
      headerName: 'Name',
      filter: 'agTextColumnFilter',
      width: 250,
      filterParams: {
        filterOptions: ['contains'],
        maxNumConditions: 0,
      },
    },
    {
      field: 'groupCount',
      headerName: 'Group Count',
      sortable: true,
      filter: 'agNumberColumnFilter',
      width: 170,
      filterParams: {
        filterOptions: [
          'equals',
          'greaterThan',
          'lessThan',
          'greaterThanOrEqualTo',
          'lessThanOrEqualTo',
        ],
        maxNumConditions: 0,
      },
    },
    {
      field: 'listCount',
      headerName: 'List Count',
      sortable: true,
      filter: 'agNumberColumnFilter',
      width: 170,
      filterParams: {
        filterOptions: [
          'equals',
          'greaterThan',
          'lessThan',
          'greaterThanOrEqualTo',
          'lessThanOrEqualTo',
        ],
        maxNumConditions: 0,
      },
    },
    {
      field: 'taskCount',
      headerName: 'Task Count',
      sortable: true,
      filter: 'agNumberColumnFilter',
      width: 170,
      filterParams: {
        filterOptions: [
          'equals',
          'greaterThan',
          'lessThan',
          'greaterThanOrEqualTo',
          'lessThanOrEqualTo',
        ],
        maxNumConditions: 0,
      },
    },
    {
      field: 'color',
      headerName: 'Color',
      sortable: false,
      cellRenderer: (params: { value: string }) => {
        const color = params.value;
        if (!color) return null;

        return (
          <div
            className="w-5 h-5 border border-gray-300 rounded my-2.5"
            style={{ backgroundColor: params.value }}
          ></div>
        );
      },
      filter: false,
    },
    {
      field: 'createdAt',
      headerName: 'Created At',
      valueFormatter: (params) => {
        const date = params.value;
        return date ? dateFormat(date) : '';
      },
      filter: 'agTextColumnFilter',
      filterParams: {
        filterOptions: ['contains'],
        maxNumConditions: 0,
      },
    },
  ]);

  const datasource = (workspaceId: string) => ({
    getRows: async (params: IServerSideGetRowsParams) => {
      const { startRow, endRow, sortModel, filterModel } = params.request;

      const sortParam = sortModel?.[0]
        ? `${sortModel[0].colId}:${sortModel[0].sort}`
        : undefined;

      const filterString = constructFilterString(filterModel);

      const response = await fetchSpacesByWorkspaceId(
        workspaceId ?? '',
        'counts',
        startRow ? startRow + 1 : 1,
        endRow,
        sortParam,
        searchParam,
        filterString
      );

      if (response) {
        params.success({
          rowData: response.spaces,
          rowCount: response.total,
        });
      } else {
        params.fail();
      }
    },
  });

  const onRowClicked = (event: any) => {
    const { id } = event.data; // Assuming "id" is the unique identifier for the row
    navigate(`/w/${workspaceId}/s/${id}`); // Adjust route as needed
  };

  const onGridReady = useCallback((event: GridReadyEvent) => {
    console.log('Grid API set on grid ready:', event.api);

    setGridApi(event.api);
    event.api.resetColumnState();
  }, []);

  const [createSpaceDialogShow, setCreateSpaceDialogShow] =
    useState<boolean>(false);
  const refreshCells = useSpacesGrid((state) => state.refreshCells);

  const handleRefresh = () => {
    refreshCells({
      force: true, // Forces the refresh
      suppressFlash: false, // Optional: Allows flash effect on cells
    });
  };

  return (
    <div>
      <button onClick={handleRefresh}>Test Refresh</button>
      <TableTopRibbon setSearchParam={setSearchParam}>
        <LightAddButton
          resourceName={'Space'}
          onClick={() => setCreateSpaceDialogShow(true)}
        />
        <Dialog
          open={createSpaceDialogShow}
          onOpenChange={setCreateSpaceDialogShow}
        >
          <DialogContent className="max-w-[425px]  sm:max-w-[600px] md:max-w-[700] ">
            <DialogHeader>
              <DialogTitle>Add Space</DialogTitle>
              <DialogDescription className="invisible">
                add space{' '}
              </DialogDescription>
            </DialogHeader>
            <SpaceForm setDialogIsOpen={setCreateSpaceDialogShow} />
          </DialogContent>
        </Dialog>
      </TableTopRibbon>

      <div
        className={`h-[500px] ${
          theme === 'dark' ? 'ag-theme-quartz-dark' : 'ag-theme-quartz'
        }`}
      >
        <AgGridReact
          className="text-xs"
          onGridReady={onGridReady}
          columnDefs={colDefs}
          defaultColDef={defaultColDef}
          rowModelType={'serverSide'}
          pagination={true}
          paginationPageSize={20}
          cacheBlockSize={20}
          animateRows={true}
          serverSideDatasource={datasource(workspaceId as string)}
          paginationPageSizeSelector={[20, 50, 100, 1000, 10000]}
          onRowClicked={onRowClicked}
          rowStyle={{ cursor: 'pointer' }}
        />
      </div>
    </div>
  );
};

I tried to create a zustand store like this then using setGridApi to set the Api .

type Store = {
    gridApi: GridApi | null; // Stores the grid API
    setGridApi: (api: GridApi) => void; // Setter for the grid API
    refreshCells: (params?: any) => void; // Function to refresh cells
};

export const useSpacesGrid = create<Store>((set, get) => ({
    gridApi: null,

    setGridApi: (api: GridApi) => {
        console.log('Setting Grid API:', api);
        set({ gridApi: api });
    },
    refreshCells: (params?: any) => {
        const gridApi = get().gridApi;
        if (gridApi) {
            gridApi.refreshCells(params);
        } else {
            console.error('Grid API is not available. Ensure the grid is initialized.');
        }
    },
}));

and trying refresh Manually instead of Invalidation but this scenario does not refresh the table .

Any help is appreciated

8
  • What is happening when you use useQuery? Are you getting any errors or the data is simply not refreshing? Commented Jan 26 at 8:34
  • Yes it does not accept data from useQuery it does not load Commented Jan 26 at 15:49
  • Have you tried to create a reference to your query client and use it directly within your datasource? Commented Apr 29 at 15:00
  • No i did not …. Commented Apr 29 at 15:18
  • 1
    @SuchitraSwain React-Router doesn't appear to be relevant here. Was your comment meant for a different post? Commented May 7 at 14:56

1 Answer 1

0

I suggest refreshing the grid in the following way: https://www.ag-grid.com/javascript-data-grid/server-side-model-updating-refresh/

Also, I’m not sure SSRM + react-query works fine together. You probably don’t need react query in this case - make direct api calls inside server side data source, as it is done in the example

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.