Search code examples
reactjsmaterial-uimui-x-data-gridtanstackreact-query

MUI X DataGrid only showing one row when paginating results


I'm using MUI X Data Grid v5 and Tanstack React Query v4 I'm trying to use pagination on my Datagrid component and when the page initially loads, it fetches and loads the grid fine as expected. The problem is introduced when I click to go to the next page of my grid, I try to refetch the data by sending a skip to my api. The is no problem with the api, it fetches the next set of data correctly. However, in the Datagrid, it only renders the last record of the result set. In my console and network response I see an array with the correct amount of records. If I navigate back it will momentarily render all the rows that were 'missing' but then continue to fetch for the onPageChange and will render correctly all the records.

Link to Code Sandbox:

Edit JS Playground (forked)

Here is what I tried:

const ApprovalGrid = () => {
  const authorization= useContext(AuthorizationContext);
  const [skip, setSkip] = useState(0);
  const [page, setPage] = useState(0);
  const pageSize = 10;
  const fetchData = async () => {
    return await doFetch(
      '/get/approvals', {
        query: {pageSize: pageSize, skip: skip },
      }),
      authorization,
    );
  };

  const { data, isLoading, isFetching, isRefetching, refetch } = useQuery(
    ['Approvals-viewAll', page],
    async () => await fetchData(),
    {
      // cacheTime: 0,
      refetchOnWindowFocus: false,
      keepPreviousData: true,
    },
  );

  const handlePageChange = (newPage) => {
    let newSkip = newPage * pageSize;
    if (data && data.count > newSkip) {
      setPage(newPage);
      setSkip(newSkip);
    }
  };

  useEffect(() => {
    refetch();
  }, [skip, page]);

  // if (isLoading || isFetching || isRefetching) {
  //   return <div>loading...</div>;
  // }
  return (
    <Box mb="12px" height="calc(100% - 16px)">
      <h1>Approvals</h1>
      <Box height="calc(100% - 150px)">
        <DataGrid
          // rows={isLoading || isFetching || isRefetching ? [] : data?.results}
          rows={data?.results}
          columns={cols}
          getRowId={(row) => row.id}
          loading={isLoading || isFetching || isRefetching}
          pagination
          pageSize={pageSize}
          rowCount={data?.count}
          onPageChange={handlePageChange}
        />
      </Box>
    </Box>
  );
};

I define skip and page so I can keep track of the current page, and update the skip based on the pageSize. If I set the if statement I have commented out, then it'll load my rows correctly on the next page. However this also causes issues with the next page button not setting correctly, where going to the next page keeps the state of it as if its still on the first page, even though its grabbing data of the second page. I'm not sure if it's the way I've set this up, or maybe I'm mis-using a pattern for the Datagrid. I don't see any issues with the way im fetching with useQuery but maybe a second pair of eyes may help.

Just a quick note- I cleaned this up a bit to remove some company logic and make it easier to read on here, let me know if something is not clear and I can update it, this is my first post on here in a while.


Solution

  • I found the issue! Since I am paginating server-side, I did not realize there was a prop for server-side pagination. My bad. I added the paginationMode="server" to the DataGrid props and it works as expected: https://codesandbox.io/p/sandbox/js-playground-forked-fjgm29?file=%2Fsrc%2FApprovalGrid.jsx%3A133%2C6.