Skip to content

[data grid] Negative page on -1 rowCount for unknown count #17431

Open
@YonderUrik

Description

@YonderUrik

Steps to reproduce

https://codesandbox.io/p/sandbox/twilight-bush-wk8glc

Current behavior

When using MUI DataGrid Pro with paginationMode="server" and rowCount={-1} (to indicate an unknown total count as per the official documentation), the pagination display behaves incorrectly.

What happens:

The label shows values like "from -25 to 0 of many" instead of a valid range.

Pagination behaves in reverse: it allows going backwards, but not forwards.

The current page index can become negative, which breaks the pagination logic.

Expected behavior

The label should correctly show something like "from X to Y of many", where X and Y are based on the current page and page size.

Pagination should allow forward navigation, and never display or enter negative pages.

Context

Below is a simplified version of the relevant parts of my implementation:

STATES:

const [paginationModel, setPaginationModel] = useState({
  page: 0,
  pageSize: 100,
  filters: [],
  pre_filters: [],
  super_filter: [],
  sort: {},
  selectedGroup: null,
});

const [hasNextPage, setHasNextPage] = useState(undefined);
const paginationMetaRef = useRef({ hasNextPage: undefined });

FETCH

const getRows = useCallback(async () => {
  try {
    setHasNextPage(undefined);
    setIsLoading(true);
    const { data } = await axiosInstance.post(`${BASE_URL}/rows`, {
      ...paginationModel,
      workspace_id: workspace_source,
    });
    setHasNextPage(data.rows.length >= paginationModel.pageSize);
    setRows(data.rows);
    setRowCount(data.totalCount); // ⚠️ could be -1 when unknown
  } catch (error) {
    toast.error(error.message || 'Errore nel recupero dei dati');
    setRows([]);
    setRowCount(0);
  } finally {
    setIsLoading(false);
  }
}, [BASE_URL, paginationModel, workspace_source]);

useEffect(() => {
  getRows();
}, [getRows]);

PAGINATION META

const paginationMeta = useMemo(() => {
  if (
    hasNextPage !== undefined &&
    paginationMetaRef.current?.hasNextPage !== hasNextPage
  ) {
    paginationMetaRef.current = { hasNextPage };
  }
  return paginationMetaRef.current;
}, [hasNextPage]);

DATAGRID

<DataGridPro
apiRef={apiRef}
slots={{
pagination: CustomPagination,
toolbar: DiscoveryToolbar,
}}
sx={{
flexGrow: 1,
width: '100%',
'& .MuiDataGrid-main': { flexGrow: 1 },
}}
rows={rows}
columns={columnsState.columns}
onColumnWidthChange={columnsState.onColumnWidthChange}
onColumnOrderChange={columnsState.onColumnOrderChange}
rowCount={rowCount}
loading={isLoading}
getRowClassName={(params) =>
username.includes(params.row.downloaded_by) ? 'downloaded' : params.indexRelativeToCurrentPage % 2 === 0 ? 'even' : 'odd'
}
slotProps={{
panel: {
anchorEl: buttonRef,
},
pagination: {
labelDisplayedRows: ({ from, to, count, ...props }) => {
console.log("props", props)
return ${fNumber(from)}-${fNumber(to)} of ${count === -1 ? 'many' : fNumber(count)}
}
},
toolbar: {
getData: getRows,
section_id: crom-disovery-default,
setButtonRef,
apiRef,
BASE_URL,
paginationModel,
rowCount,
groupByOptions,
setSelectedGroup,
openFilters,
setOpenFilters,
detailsColumns: discoveryInfo.find((item) => item.type ===
'default_discovery_columns')?.columns || [],
rowSelectionModel,
workspace_source,
current_analysis_type: null,
workspaceInfo
},
headerFilterCell: {
InputComponentProps: {
size: 'small',
},
},
row: {
onContextMenu: handleContextMenu,
style: { cursor: 'context-menu' },
},
}}
initialState={{
density: 'compact',
}}
density='compact'
// PAGINATION
paginationMeta={paginationMeta}
paginationModel={paginationModel}
onPaginationModelChange={handlePaginationModelChange}
paginationMode="server"
pageSizeOptions={[100, 200, 500]}
pagination
// ROW ID
getRowId={(row) => paginationModel.selectedGroup ? JSON.stringify(row._id) : row?._id?.$oid}
// FILTERS
unstable_headerFilters
filterMode="server"
onFilterModelChange={onFilterChange}
// SORTING
sortingMode="server"
onSortModelChange={handleSortModelChange}
// SELECTION
rowSelectionModel={rowSelectionModel}
checkboxSelection={paginationModel.selectedGroup === null}
disableRowSelectionOnClick
keepNonExistentRowsSelected
onRowSelectionModelChange={(newRowSelectionModel) => {
setRowSelectionModel(newRowSelectionModel);
}}
/>

CUSTOM PAGINATION

function Pagination(props) {
const { page, onPageChange, className } = props;
⚠️ page is set to -1 IDK WHY
const apiRef = useGridApiContext();
const pageCount = useGridSelector(apiRef, gridPageCountSelector);

return (
<MuiPagination
color="primary"
className={className}
count={pageCount}
page={page + 1}
onChange={(event, newPage) => {
console.log("newPage", newPage)
onPageChange(event, newPage - 1);
}}
/>
);
}

function CustomPagination(props) {
return <GridPagination ActionsComponent={Pagination} {...props} />;
}

Your environment

npx @mui/envinfo
  System:
OS: Linux 5.15 Ubuntu 22.04.5 LTS 22.04.5 LTS (Jammy Jellyfish)
Binaries:
Node: 20.12.2 - ~/.nvm/versions/node/v20.12.2/bin/node
npm: 10.9.2 - ~/webapps/apps.convey.tools/convey-apps/frontend/node_modules/.bin/npm
pnpm: Not Found
Browsers:
Chrome: Not Found
npmPackages:
@emotion/react: ^11.13.3 => 11.14.0
@emotion/styled: ^11.13.0 => 11.14.0
@mui/base: ^5.0.0-beta.40 => 5.0.0-beta.40
@mui/core-downloads-tracker: 6.4.5
@mui/icons-material: ^6.1.2 => 6.1.2
@mui/lab: ^5.0.0-alpha.134 => 5.0.0-alpha.166
@mui/material: ^6.1.6 => 6.4.5
@mui/private-theming: 5.15.12
@mui/styled-engine: 6.1.6
@mui/styled-engine-sc: ^6.1.6 => 6.1.6
@mui/styles: ^5.15.12 => 5.15.12
@mui/system: ^6.1.6 => 6.1.6
@mui/types: 7.2.21
@mui/utils: 6.1.6
@mui/x-charts: ^7.22.2 => 7.22.2
@mui/x-charts-vendor: 7.20.0
@mui/x-data-grid: 6.20.4
@mui/x-data-grid-pro: ^6.18.7 => 6.20.4
@mui/x-date-pickers: ^7.1.0 => 7.1.0
@mui/x-date-pickers-pro: ^7.1.0 => 7.27.0
@mui/x-internals: 7.26.0
@mui/x-license: 7.26.0
@mui/x-license-pro: ^6.10.2 => 6.10.2
@mui/x-tree-view: ^7.23.0 => 7.23.0
@types/react: ^18.2.12 => 18.2.60
react: ^18.2.0 => 18.2.0
react-dom: ^18.2.0 => 18.2.0
styled-components: ^6.1.13 => 6.1.13
typescript: ^4.9.5 => 4.9.5

Search keywords: unkown count negative pagination

Order ID: 101883

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug 🐛Something doesn't workcomponent: data gridThis is the name of the generic UI component, not the React module!feature: PaginationRelated to the data grid Pagination featurestaleThis PR has been inactive for more than 30 days. It will get closed after 90 days of inactivity.status: waiting for authorIssue with insufficient informationsupport: pro standardSupport request from a Pro standard plan user. https://mui.com/legal/technical-support-sla/v6.x

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions