I have basic react example for learning and I use material-table in one of my components. Each time I change the page and re-open it (unmount and mount component), my component which contains material-table load more slowly. I share my code below.
import MaterialTable from 'material-table'; const columns = [ { title: 'Id', field: 'id', hidden: true }, { title: 'Username', field: 'username' }, { title: 'Name', field: 'name' }, { title: 'Phone', field: 'phone'} ]; const tableData = [ { id: 1, username: "User-1", name: "name-1", phone: "555 444 33 22" }, { id: 2, username: "User-2", name: "name-2", phone: "111 222 33 44" }, { id: 3, username: "User-3", name: "name-3", phone: "999 999 99 99" } ]; const MTable = () => { return ( <MaterialTable title="Basic Search Preview" columns={columns} data={tableData} options={{search: true }} /> ) } export default MTable
After long search I did not find any solution, and after long try I just change the place of columns definition like below.
const MTable = () => { const columns = [ { title: 'Id', field: 'id', hidden: true }, { title: 'Username', field: 'username' }, { title: 'Name', field: 'name' }, { title: 'Phone', field: 'phone'} ]; return ( <MaterialTable title="Basic Search Preview" columns={columns} data={tableData} options={{search: true }} /> ) }
This change solve my problem but I really want to learn why this happened. When I made the column definition outside of the method why memory leak and render slowed each page change. At the same time, when I moved into method what changed?
Advertisement
Answer
analysis
material-table adds a property column.tableData
to each column of your columns
list, and then there is an assignment that effectively does something like (see file data-manager.js):
column[0].tableData.width = "calc(" + ... + column[0].tableData.width + ... + column[1].tableData.width + ... + ")" column[1].tableData.width = "calc(" + ... ...
Because the columns are in the global scope and are not destroyed on every unmount, this lets the string tableData.width
grow exponentially. I guess the increasingly long time it takes comes from these increasingly many nested “calc()” invocations.
conclusion
I hesitate to call this a bug in material-table.
It looks like material-table expects the columns to be created on every render (and not to be persistent). Fair enough, but I would at least call this unexpected behavior for somebody who is used to work in React, and there should be a warning about this in the documentation. I also think even then that could have been implemented foolproof. (if somebody disagrees, I’d like to read reasons in the comments)
example
The first time the component is mounted the tableData.width
is:
calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) )) / 3)
After un-mount and a second mount the width tableData.width
is:
calc((100% - (0px + calc((100% - (0px + calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3) + calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3) + calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3) )) / 3) + calc((100% - (0px + calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3) + calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3) + calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3) )) / 3) + calc((100% - (0px + calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3) + calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3) + calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3) )) / 3) )) / 3)"