Breaking Changes

A list of breaking changes since forking from mbrn/material-table (fork was created around mbrn/material-table v1.60.0)



Version 3.0.0 is where we started supporting Material-UI v4.12. If you are using anything above v3.0.0 you should be good to use Material-UI v4.12

If you use Material-UI v5, try out the next branch


Version 3.x.x inherits all breaking changes from v2.x.x


Most support for v2.x.x has been dropped, we are actively deploying to v3.x.x and will working on moving to v5 permanently

The following breaking changes are specific to @material-ui v5


padding now accepts 'normal' or 'dense'


onChangeRowsPerPage has been renamed to onRowsPerPageChange


onChangePage has been renamed to onPageChange

Detail Panel#

The detail panel is now a full react component and allows hooks and animations. To access the passed data passed as props, deconstruct them instead of accessing directly as previously:

detailPanel={({ rowData }) => {...}

tooltip: 'Show Name',
render: ({ rowData }) => {...}


To persist edit/sort/detail panel state between renders, a new unique key was added to the rows/data props: id. If an unique id is added to each row, the state can be persisted between renders similar to the key prop of reacts rendering of arrays. It is not required and the index will be used as a fallback. Nevertheless, a console warning will be displayed. For more details, see this PR or this issue.

The default key id can be overridden with the option idSynonym in case the data provided has a different property for the id. More in the types.



Due to jspdf absolutely bloating our bundle, we had to make breaking changes to the way exporting data is handled.

See here for more.

Columns Button#


This is also referred to as the exportMenu

Is the action which shows a menu that allows a user to hide/show columns.


Column Hidden Defaults#

All columns used to be hidden from the Columns Button Menu by default, this has since changed.

In order to achieve the same behavior as before this breaking change, you have two options:

Data and column object reference#

The mutation of data and columns to add the tableData object was removed.

This will remove the object reference for the callbacks as well, so that if you rely on object comparision to find your data, this will no longer work (Thread):

onRowClick={(event, clickedRow)=> {
// Will now always return undefined because reference changed
const existingRow = data.find(d => d === clickedRow)

Instead this works:

onRowClick={(event, clickedRow)=> {
// Finding the object with an internal id/unique property
const existingRow = data.find(d => ===
// Accessing the index
const existingRow = data[]

Functions in the options/columns props#

Due to the removal of the mutation of the column and data props, if columns or options changed by a deep comparison, the data gets rested to reflect the new state, e.g. new pageSize or current page.

Since functions can only be compared by object reference, the reference of the optional rowStyle or cellStyle function must be stable between renders. This also applies to the column array.

options={{cellStyle: () => ({color: 'red'})}} // This will result in a reset of the table state between renders.

Use React.useCallback or declare these functions outside of the component function to create a stable object reference.

const cellStyle = React.useCallback(() => ({color: 'red'}), [])
options={{cellStyle: cellStyle}} // useCallback will create a stable reference

See here for more info + Live Demos (editable playground)