The Ultimate Guide to Material-UI Table Pagination (MUI v5)

Table pagination can be broken into two conceptual pieces: the UI interface for changing pages, and the paginated data request. Material-UI’s TablePagination component is a robust component for solving the UI interface.

The MUI TablePagination component is a dynamic and highly customizable component. It has 18 props listed in the docs, and these control everything from button icons to the root component that TablePagination renders.

The component also exposes several events through these props. These events pass the necessary values so that the developer can implement the data side of pagination, i.e. partitioning an array of values for local pagination or passing the necessary properties for remote pagination.

In the following example, I will enable every prop and discuss how to implement local and remote pagination. A Code Sandbox link with full React Code is in the Resources section.

How to Use the TablePagination Component (Every Prop Enabled)

Almost every feature of the TablePagination component can be enabled, disabled, or customized through the excellent API.

I created the below Material-UI Table with Pagination:

Material-UI Table Pagination Customized
Custom Material-UI Table Pagination Component

It is important to take a look at the DOM in order to understand the TablePagination component. There are so many subcomponents I can’t capture them in one screenshot. The component is built from MUI subcomponents such as Toolbar, Input, and IconButton. Keep this in mind as we learn about the props and styling options for the pagination component.

Material-UI TablePagination Component DOM Rendering
Material-UI TablePagination Component DOM Rendering

TablePagination is usually included in the footer of the table. I set every config (except a few which conflict) and will discuss them below. The conflicting configs are commented out in the code below. Styling configs are discussed in a separate section below.

  <TableBody /> //See Code Sandbox for TableBody implementation
        rowsPerPageOptions={[5, 10, 25]}
        labelDisplayedRows={({ page }) => {
          return `Page: ${page}`;
          color: "secondary"
        nextIconButtonProps={{ color: "secondary" }}
          inputProps: {
            "aria-label": "page number"
        //sx and classes prop discussed in styling section

TablePagination State Management Configs

The following help maintain the metadata about the table’s current data and settings:

  • count – the total rows available
  • rowsPerPage – visible rows per page, user-configurable through a dropdown
  • page – the current page

The three values above are maintained in React useState constants in my live Code Sandbox.

TablePagination Event Listeners

The following accept a handler for an event:

  • onPageChange – this passes the event object and the new page value
  • onRowsPerPageChange – this passes the event object when the user selects a new ‘visible rows per page’ value

My Code Sandbox is a fork of an example in the MUI docs and I have not changed the handlers from their example. Notice how they reset the page after onRowsPerPageChange fires:

const handleChangePage = (event, newPage) => {

const handleChangeRowsPerPage = (event) => {
  setRowsPerPage(parseInt(, 10));

TablePagination Labels and Options

The following affect the displayed text or values in the component:

  • rowsPerPageOptions – the possible values in the ‘rows per page’ dropdown
  • labelRowsPerPage – a simple text label for the ‘rows per page’ dropdown. Alternatively it can accept a node if you want to affect the underlying component. In my code I passed {<span>Rows:</span>}
  • labelDisplayedRows – this prop accepts a callback as it’s prop and passes the values from, to, and count to the callback. The purpose of this is to customize the label for displayed rows and let it render text dynamically based on current table state

TablePagination Subcomponent Props

The following pass props to subcomponents (or composing components) of the TabPagination component, render different subcomponents, or disable the subcomponents:

  • backIconButtonProps – passes props to the ‘back’ IconButton subcomponent. Interestingly not all props of the IconButton worked, for example I could not change the size
  • nextIconButtonProps – passes props to the ‘next’ IconButton subcomponent
  • SelectProps – passes props to the Select ‘rows per page’ dropdown
  • showFirstButton – enable the ‘Go to first page’ button. Disabled by default
  • showLastButton enable the ‘Go to last page’ button. Disabled by default
  • ActionsComponent – this allows for complete customization of the actions section, i.e. the forward/back buttons. Use this if you want to create your own Actions component bar. If you use this prop, other props such as backIconButtonProps will no longer work (this is by design).
  • component – this allows for complete customization of the root wrapping component. It has similar ramifications as using ActionsComponent, but takes effect higher in the DOM nesting. Uncomment my component={Box} code if you want to see an example in the Code Sandbox.

Pagination with Local Data

Pagination in the Material-UI Table is far more about the UI component than it is about the parsing and partitioning of the data for viewing data one page at a time. However, it is important to understand the mechanics behind the data rendering.

Pagination of data can be thought of as a filter based on where an element or row is in the dataset. The MUI example from the docs has a great method for creating this filter:

  rowsPerPage > 0 
    ? data.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
    : data
).map((row) => (...) //TableRow JSX goes in the return

This simple algorithm either returns a subset of the data as an array (if pagination is enabled) or returns all the data.

Pagination with Remote Data

If you need to paginate from a remote data source, make sure to do two things:

  1. Pass any necessary state variables. You will pass these as url params or in the body of the request
  2. If you are using my example or the MUI team’s example, remove the local pagination algorithm mentioned above

In my code, I have a useEffect hook that calls a Star Wars data endpoint on page load. If supported by the endpoint, I could add ?page={page}&count={count} to the call to enable pagination.

React.useEffect(() => {
    //alternative to
    .then((response) => response.json())
    .then((data) => setData(data));

  }, []);

Styling the Material-UI TablePagination Component

Like all MUI components, TablePagination has a styling API that exposes global classes that can be targeted with selectors. A few example classes are .MuiTablePagination-toolbar, .MuiTablePagination-input, and .MuiTablePagination-selectLabel.

First I set background color by targeting the Toolbar subcomponent in the Pagination component. Then I added two of the nested selectors to the sx prop to style the select label and the input dropdown text with blue color and bold weight.

  ".MuiTablePagination-toolbar": {
    backgroundColor: "rgba(100,100,100,0.5)"
  ".MuiTablePagination-selectLabel, .MuiTablePagination-input": {
    fontWeight: "bold",
    color: "blue"

Alternatively, you can make use of the classes prop and target the CSS rules (root, toolbar, and selectLabel) that correspond to the above global classes.

As a reminder, some of the TablePagination subcomponents, such as the IconButtons. can be styled through props discussed above.


Code Sandbox Link

Material Table for React is a third-party library built on MUI’s table component. It adds a lot of great features and configs.

Read how to set a sticky first column in MUI’s table here.

Here’s how to add a search bar to Material-UI’s table component.

Material-UI Table Docs

Material-UI TablePagination API

Share this post:

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.