T
TanStack2mo ago
flat-fuchsia

Problems integrating Tanstack Query with MUI X Data Grid server-sided data source

Hi all, I'm facing a problem integrating Tanstack Query with @mui/x-data-grid server sided data (https://mui.com/x/react-data-grid/server-side-data/). Based on a different post in the MUI discord I got to the conclusion that this should be feasible by providing a queryClient.fetchQuery to the getRows function for the dataSource however the problem I am now facing is that I get the following error from the onDataSourceError:
GridGetRowsError: Missing queryFn: '["my-identifier",{"filterModel":{"items":[],"logicOperator":"and","quickFilterLogicOperator":"and","quickFilterValues":[]},"page":0,"pageSize":10,"sortModel":[{"field":"startDate","sort":"desc"}]},false]'
GridGetRowsError: Missing queryFn: '["my-identifier",{"filterModel":{"items":[],"logicOperator":"and","quickFilterLogicOperator":"and","quickFilterValues":[]},"page":0,"pageSize":10,"sortModel":[{"field":"startDate","sort":"desc"}]},false]'
This is quite understandable as the way the code is structured is that we have custom hooks around useQuery hooks i.e.:
export function useData(queryOptions: GridPaginationModel, archived: boolean) {
return useQuery({
queryKey: ['my-identifier', queryOptions, archived],
queryFn: async () => { /* ... impl ... */ }
})
}
export function useData(queryOptions: GridPaginationModel, archived: boolean) {
return useQuery({
queryKey: ['my-identifier', queryOptions, archived],
queryFn: async () => { /* ... impl ... */ }
})
}
However I am no longer calling this function anywhere in the component that render the datagrid, as its output is no longer relevant as the same call should be made by MUI. That is to say, the component that renders the data grid is roughly:
import { useData } from '../my-hook';
import { DataGrid, type GridDataSource } from '@mui/x-data-grid';
import { useQueryClient } from '@tanstack/react-query';

function MyComponent({ archive = false }: MyComponentProps) {
const queryClient = useQueryClient();

const dataSource: GridDataSource = {
getRows: async (queryOptions): Promise<GridGetRowsResponse> = {
return queryClient.fetchQuery('my-identifier', queryOptions, archive);
}
}

const columns = [ /* impl */ ]

return (
<DataGrid dataSource={dataSource} columns={columns} />
);
}
import { useData } from '../my-hook';
import { DataGrid, type GridDataSource } from '@mui/x-data-grid';
import { useQueryClient } from '@tanstack/react-query';

function MyComponent({ archive = false }: MyComponentProps) {
const queryClient = useQueryClient();

const dataSource: GridDataSource = {
getRows: async (queryOptions): Promise<GridGetRowsResponse> = {
return queryClient.fetchQuery('my-identifier', queryOptions, archive);
}
}

const columns = [ /* impl */ ]

return (
<DataGrid dataSource={dataSource} columns={columns} />
);
}
With the old version of MUI X Data Grid (v7) which did not have this dataSource functionality yet I would have a line const myData = useData() in the component but as you can see that is gone now. I have also tried simply calling useData() without storing the response in a constant to "register" the query, but then I still get the same error, because the queryOptions from MUI differ from the default query options (unknown/empty). If I do mimic the query options from MUI in this, I then get an infinitely looping backend call.
6 Replies
flat-fuchsia
flat-fuchsiaOP2mo ago
bumping this up, still hoping someone can assist here
crude-lavender
crude-lavender2mo ago
@Favna I am using tanstack query + MUI Data Grid v8 and hadn't even heard of the dataSource attribute until now. are you committed to using this attribute? I feel like query gives you the functionality that DataGrid gives you with the dataSource prop
flat-fuchsia
flat-fuchsiaOP2mo ago
Ideally yes. We rely heavily on server sided data which while it works with our current setup is less than ideal in implementation and we'd love to be able to use the new server sided data method. Pretty much for all the benefits that MUI also describes in their docs.
crude-lavender
crude-lavender2mo ago
fwiw I'm also doing server-side data but not using the dataSource prop – let me re-read the docs to see if there's anything I'm missing out on by doing it myself instead of using that prop ok, re-read it (for the most part). it seems like your code should work but is it just that you're potentially passing in the wrong thing into .fetchQuery? I instead might expect to be...
function MyComponent({ archive = false }: MyComponentProps) {
const queryClient = useQueryClient();

const dataSource: GridDataSource = {
getRows: async (params: GridGetRowsParams): Promise<GridGetRowsResponse> {
return queryClient.fetchQuery({
queryKey: [
'my-identifier',
formatMuiDataGridParameters(params),
archive
],
queryFn: async () => {
return fetch('/your-endpoint-here')
}
});
}
}

const columns = [ /* impl */ ]

return (
<DataGrid dataSource={dataSource} columns={columns} />
);
}

function formatMuiDataGridParameters (params: GridGetRowsParams) {
return {
pageSize: params.page_size, // or whatever it is'
// otehers...
}
}
function MyComponent({ archive = false }: MyComponentProps) {
const queryClient = useQueryClient();

const dataSource: GridDataSource = {
getRows: async (params: GridGetRowsParams): Promise<GridGetRowsResponse> {
return queryClient.fetchQuery({
queryKey: [
'my-identifier',
formatMuiDataGridParameters(params),
archive
],
queryFn: async () => {
return fetch('/your-endpoint-here')
}
});
}
}

const columns = [ /* impl */ ]

return (
<DataGrid dataSource={dataSource} columns={columns} />
);
}

function formatMuiDataGridParameters (params: GridGetRowsParams) {
return {
pageSize: params.page_size, // or whatever it is'
// otehers...
}
}
oops srry, that's wrong. lemme fix updated @Favna sorry, I should've pinged when I updated it, since I know Discord doesn't send notifs for edits
flat-fuchsia
flat-fuchsiaOP2mo ago
I only passed the queryKey since we have custom hooks wrapper around useQuery as shown above for both using them elsewhere and being able to unit test them
crude-lavender
crude-lavender2mo ago
right but is that being applied to fetchQuery as well?

Did you find this page helpful?