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
useQuery? Are you getting any errors or the data is simply not refreshing?